1*263b2ba5SJacek Lawrynowicz // SPDX-License-Identifier: GPL-2.0-only 2*263b2ba5SJacek Lawrynowicz /* 3*263b2ba5SJacek Lawrynowicz * Copyright (C) 2020-2023 Intel Corporation 4*263b2ba5SJacek Lawrynowicz */ 5*263b2ba5SJacek Lawrynowicz 6*263b2ba5SJacek Lawrynowicz #include <linux/circ_buf.h> 7*263b2ba5SJacek Lawrynowicz #include <linux/highmem.h> 8*263b2ba5SJacek Lawrynowicz 9*263b2ba5SJacek Lawrynowicz #include "ivpu_drv.h" 10*263b2ba5SJacek Lawrynowicz #include "ivpu_hw_mtl_reg.h" 11*263b2ba5SJacek Lawrynowicz #include "ivpu_hw_reg_io.h" 12*263b2ba5SJacek Lawrynowicz #include "ivpu_mmu.h" 13*263b2ba5SJacek Lawrynowicz #include "ivpu_mmu_context.h" 14*263b2ba5SJacek Lawrynowicz 15*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_IDR0_REF 0x080f3e0f 16*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_IDR0_REF_SIMICS 0x080f3e1f 17*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_IDR1_REF 0x0e739d18 18*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_IDR3_REF 0x0000003c 19*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_IDR5_REF 0x00040070 20*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_IDR5_REF_SIMICS 0x00000075 21*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_IDR5_REF_FPGA 0x00800075 22*263b2ba5SJacek Lawrynowicz 23*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_CDTAB_ENT_SIZE 64 24*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_CDTAB_ENT_COUNT_LOG2 8 /* 256 entries */ 25*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_CDTAB_ENT_COUNT ((u32)1 << IVPU_MMU_CDTAB_ENT_COUNT_LOG2) 26*263b2ba5SJacek Lawrynowicz 27*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_STREAM_ID0 0 28*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_STREAM_ID3 3 29*263b2ba5SJacek Lawrynowicz 30*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_STRTAB_ENT_SIZE 64 31*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_STRTAB_ENT_COUNT 4 32*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_STRTAB_CFG_LOG2SIZE 2 33*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_STRTAB_CFG IVPU_MMU_STRTAB_CFG_LOG2SIZE 34*263b2ba5SJacek Lawrynowicz 35*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_Q_COUNT_LOG2 4 /* 16 entries */ 36*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_Q_COUNT ((u32)1 << IVPU_MMU_Q_COUNT_LOG2) 37*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_Q_WRAP_BIT (IVPU_MMU_Q_COUNT << 1) 38*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_Q_WRAP_MASK (IVPU_MMU_Q_WRAP_BIT - 1) 39*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_Q_IDX_MASK (IVPU_MMU_Q_COUNT - 1) 40*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_Q_IDX(val) ((val) & IVPU_MMU_Q_IDX_MASK) 41*263b2ba5SJacek Lawrynowicz 42*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_CMDQ_CMD_SIZE 16 43*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_CMDQ_SIZE (IVPU_MMU_Q_COUNT * IVPU_MMU_CMDQ_CMD_SIZE) 44*263b2ba5SJacek Lawrynowicz 45*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_EVTQ_CMD_SIZE 32 46*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_EVTQ_SIZE (IVPU_MMU_Q_COUNT * IVPU_MMU_EVTQ_CMD_SIZE) 47*263b2ba5SJacek Lawrynowicz 48*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_CMD_OPCODE GENMASK(7, 0) 49*263b2ba5SJacek Lawrynowicz 50*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_CMD_SYNC_0_CS GENMASK(13, 12) 51*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_CMD_SYNC_0_MSH GENMASK(23, 22) 52*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_CMD_SYNC_0_MSI_ATTR GENMASK(27, 24) 53*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_CMD_SYNC_0_MSI_ATTR GENMASK(27, 24) 54*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_CMD_SYNC_0_MSI_DATA GENMASK(63, 32) 55*263b2ba5SJacek Lawrynowicz 56*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_CMD_CFGI_0_SSEC BIT(10) 57*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_CMD_CFGI_0_SSV BIT(11) 58*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_CMD_CFGI_0_SSID GENMASK(31, 12) 59*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_CMD_CFGI_0_SID GENMASK(63, 32) 60*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_CMD_CFGI_1_RANGE GENMASK(4, 0) 61*263b2ba5SJacek Lawrynowicz 62*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_CMD_TLBI_0_ASID GENMASK(63, 48) 63*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_CMD_TLBI_0_VMID GENMASK(47, 32) 64*263b2ba5SJacek Lawrynowicz 65*263b2ba5SJacek Lawrynowicz #define CMD_PREFETCH_CFG 0x1 66*263b2ba5SJacek Lawrynowicz #define CMD_CFGI_STE 0x3 67*263b2ba5SJacek Lawrynowicz #define CMD_CFGI_ALL 0x4 68*263b2ba5SJacek Lawrynowicz #define CMD_CFGI_CD 0x5 69*263b2ba5SJacek Lawrynowicz #define CMD_CFGI_CD_ALL 0x6 70*263b2ba5SJacek Lawrynowicz #define CMD_TLBI_NH_ASID 0x11 71*263b2ba5SJacek Lawrynowicz #define CMD_TLBI_EL2_ALL 0x20 72*263b2ba5SJacek Lawrynowicz #define CMD_TLBI_NSNH_ALL 0x30 73*263b2ba5SJacek Lawrynowicz #define CMD_SYNC 0x46 74*263b2ba5SJacek Lawrynowicz 75*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_EVT_F_UUT 0x01 76*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_EVT_C_BAD_STREAMID 0x02 77*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_EVT_F_STE_FETCH 0x03 78*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_EVT_C_BAD_STE 0x04 79*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_EVT_F_BAD_ATS_TREQ 0x05 80*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_EVT_F_STREAM_DISABLED 0x06 81*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_EVT_F_TRANSL_FORBIDDEN 0x07 82*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_EVT_C_BAD_SUBSTREAMID 0x08 83*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_EVT_F_CD_FETCH 0x09 84*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_EVT_C_BAD_CD 0x0a 85*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_EVT_F_WALK_EABT 0x0b 86*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_EVT_F_TRANSLATION 0x10 87*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_EVT_F_ADDR_SIZE 0x11 88*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_EVT_F_ACCESS 0x12 89*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_EVT_F_PERMISSION 0x13 90*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_EVT_F_TLB_CONFLICT 0x20 91*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_EVT_F_CFG_CONFLICT 0x21 92*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_EVT_E_PAGE_REQUEST 0x24 93*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_EVT_F_VMS_FETCH 0x25 94*263b2ba5SJacek Lawrynowicz 95*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_EVT_OP_MASK GENMASK_ULL(7, 0) 96*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_EVT_SSID_MASK GENMASK_ULL(31, 12) 97*263b2ba5SJacek Lawrynowicz 98*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_Q_BASE_RWA BIT(62) 99*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_Q_BASE_ADDR_MASK GENMASK_ULL(51, 5) 100*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_STRTAB_BASE_RA BIT(62) 101*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_STRTAB_BASE_ADDR_MASK GENMASK_ULL(51, 6) 102*263b2ba5SJacek Lawrynowicz 103*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_IRQ_EVTQ_EN BIT(2) 104*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_IRQ_GERROR_EN BIT(0) 105*263b2ba5SJacek Lawrynowicz 106*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_CR0_ATSCHK BIT(4) 107*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_CR0_CMDQEN BIT(3) 108*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_CR0_EVTQEN BIT(2) 109*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_CR0_PRIQEN BIT(1) 110*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_CR0_SMMUEN BIT(0) 111*263b2ba5SJacek Lawrynowicz 112*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_CR1_TABLE_SH GENMASK(11, 10) 113*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_CR1_TABLE_OC GENMASK(9, 8) 114*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_CR1_TABLE_IC GENMASK(7, 6) 115*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_CR1_QUEUE_SH GENMASK(5, 4) 116*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_CR1_QUEUE_OC GENMASK(3, 2) 117*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_CR1_QUEUE_IC GENMASK(1, 0) 118*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_CACHE_NC 0 119*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_CACHE_WB 1 120*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_CACHE_WT 2 121*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_SH_NSH 0 122*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_SH_OSH 2 123*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_SH_ISH 3 124*263b2ba5SJacek Lawrynowicz 125*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_CMDQ_OP GENMASK_ULL(7, 0) 126*263b2ba5SJacek Lawrynowicz 127*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_CD_0_TCR_T0SZ GENMASK_ULL(5, 0) 128*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_CD_0_TCR_TG0 GENMASK_ULL(7, 6) 129*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_CD_0_TCR_IRGN0 GENMASK_ULL(9, 8) 130*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_CD_0_TCR_ORGN0 GENMASK_ULL(11, 10) 131*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_CD_0_TCR_SH0 GENMASK_ULL(13, 12) 132*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_CD_0_TCR_EPD0 BIT_ULL(14) 133*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_CD_0_TCR_EPD1 BIT_ULL(30) 134*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_CD_0_ENDI BIT(15) 135*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_CD_0_V BIT(31) 136*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_CD_0_TCR_IPS GENMASK_ULL(34, 32) 137*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_CD_0_TCR_TBI0 BIT_ULL(38) 138*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_CD_0_AA64 BIT(41) 139*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_CD_0_S BIT(44) 140*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_CD_0_R BIT(45) 141*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_CD_0_A BIT(46) 142*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_CD_0_ASET BIT(47) 143*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_CD_0_ASID GENMASK_ULL(63, 48) 144*263b2ba5SJacek Lawrynowicz 145*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_CD_1_TTB0_MASK GENMASK_ULL(51, 4) 146*263b2ba5SJacek Lawrynowicz 147*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_STE_0_S1CDMAX GENMASK_ULL(63, 59) 148*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_STE_0_S1FMT GENMASK_ULL(5, 4) 149*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_STE_0_S1FMT_LINEAR 0 150*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_STE_DWORDS 8 151*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_STE_0_CFG_S1_TRANS 5 152*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_STE_0_CFG GENMASK_ULL(3, 1) 153*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_STE_0_S1CTXPTR_MASK GENMASK_ULL(51, 6) 154*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_STE_0_V BIT(0) 155*263b2ba5SJacek Lawrynowicz 156*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_STE_1_STRW_NSEL1 0ul 157*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_STE_1_CONT GENMASK_ULL(16, 13) 158*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_STE_1_STRW GENMASK_ULL(31, 30) 159*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_STE_1_PRIVCFG GENMASK_ULL(49, 48) 160*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_STE_1_PRIVCFG_UNPRIV 2ul 161*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_STE_1_INSTCFG GENMASK_ULL(51, 50) 162*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_STE_1_INSTCFG_DATA 2ul 163*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_STE_1_MEV BIT(19) 164*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_STE_1_S1STALLD BIT(27) 165*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_STE_1_S1C_CACHE_NC 0ul 166*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_STE_1_S1C_CACHE_WBRA 1ul 167*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_STE_1_S1C_CACHE_WT 2ul 168*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_STE_1_S1C_CACHE_WB 3ul 169*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_STE_1_S1CIR GENMASK_ULL(3, 2) 170*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_STE_1_S1COR GENMASK_ULL(5, 4) 171*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_STE_1_S1CSH GENMASK_ULL(7, 6) 172*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_STE_1_S1DSS GENMASK_ULL(1, 0) 173*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_STE_1_S1DSS_TERMINATE 0x0 174*263b2ba5SJacek Lawrynowicz 175*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_REG_TIMEOUT_US (10 * USEC_PER_MSEC) 176*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_QUEUE_TIMEOUT_US (100 * USEC_PER_MSEC) 177*263b2ba5SJacek Lawrynowicz 178*263b2ba5SJacek Lawrynowicz #define IVPU_MMU_GERROR_ERR_MASK ((REG_FLD(MTL_VPU_HOST_MMU_GERROR, CMDQ)) | \ 179*263b2ba5SJacek Lawrynowicz (REG_FLD(MTL_VPU_HOST_MMU_GERROR, EVTQ_ABT)) | \ 180*263b2ba5SJacek Lawrynowicz (REG_FLD(MTL_VPU_HOST_MMU_GERROR, PRIQ_ABT)) | \ 181*263b2ba5SJacek Lawrynowicz (REG_FLD(MTL_VPU_HOST_MMU_GERROR, MSI_CMDQ_ABT)) | \ 182*263b2ba5SJacek Lawrynowicz (REG_FLD(MTL_VPU_HOST_MMU_GERROR, MSI_EVTQ_ABT)) | \ 183*263b2ba5SJacek Lawrynowicz (REG_FLD(MTL_VPU_HOST_MMU_GERROR, MSI_PRIQ_ABT)) | \ 184*263b2ba5SJacek Lawrynowicz (REG_FLD(MTL_VPU_HOST_MMU_GERROR, MSI_ABT))) 185*263b2ba5SJacek Lawrynowicz 186*263b2ba5SJacek Lawrynowicz static char *ivpu_mmu_event_to_str(u32 cmd) 187*263b2ba5SJacek Lawrynowicz { 188*263b2ba5SJacek Lawrynowicz switch (cmd) { 189*263b2ba5SJacek Lawrynowicz case IVPU_MMU_EVT_F_UUT: 190*263b2ba5SJacek Lawrynowicz return "Unsupported Upstream Transaction"; 191*263b2ba5SJacek Lawrynowicz case IVPU_MMU_EVT_C_BAD_STREAMID: 192*263b2ba5SJacek Lawrynowicz return "Transaction StreamID out of range"; 193*263b2ba5SJacek Lawrynowicz case IVPU_MMU_EVT_F_STE_FETCH: 194*263b2ba5SJacek Lawrynowicz return "Fetch of STE caused external abort"; 195*263b2ba5SJacek Lawrynowicz case IVPU_MMU_EVT_C_BAD_STE: 196*263b2ba5SJacek Lawrynowicz return "Used STE invalid"; 197*263b2ba5SJacek Lawrynowicz case IVPU_MMU_EVT_F_BAD_ATS_TREQ: 198*263b2ba5SJacek Lawrynowicz return "Address Request disallowed for a StreamID"; 199*263b2ba5SJacek Lawrynowicz case IVPU_MMU_EVT_F_STREAM_DISABLED: 200*263b2ba5SJacek Lawrynowicz return "Transaction marks non-substream disabled"; 201*263b2ba5SJacek Lawrynowicz case IVPU_MMU_EVT_F_TRANSL_FORBIDDEN: 202*263b2ba5SJacek Lawrynowicz return "MMU bypass is disallowed for this StreamID"; 203*263b2ba5SJacek Lawrynowicz case IVPU_MMU_EVT_C_BAD_SUBSTREAMID: 204*263b2ba5SJacek Lawrynowicz return "Invalid StreamID"; 205*263b2ba5SJacek Lawrynowicz case IVPU_MMU_EVT_F_CD_FETCH: 206*263b2ba5SJacek Lawrynowicz return "Fetch of CD caused external abort"; 207*263b2ba5SJacek Lawrynowicz case IVPU_MMU_EVT_C_BAD_CD: 208*263b2ba5SJacek Lawrynowicz return "Fetched CD invalid"; 209*263b2ba5SJacek Lawrynowicz case IVPU_MMU_EVT_F_WALK_EABT: 210*263b2ba5SJacek Lawrynowicz return " An external abort occurred fetching a TLB"; 211*263b2ba5SJacek Lawrynowicz case IVPU_MMU_EVT_F_TRANSLATION: 212*263b2ba5SJacek Lawrynowicz return "Translation fault"; 213*263b2ba5SJacek Lawrynowicz case IVPU_MMU_EVT_F_ADDR_SIZE: 214*263b2ba5SJacek Lawrynowicz return " Output address caused address size fault"; 215*263b2ba5SJacek Lawrynowicz case IVPU_MMU_EVT_F_ACCESS: 216*263b2ba5SJacek Lawrynowicz return "Access flag fault"; 217*263b2ba5SJacek Lawrynowicz case IVPU_MMU_EVT_F_PERMISSION: 218*263b2ba5SJacek Lawrynowicz return "Permission fault occurred on page access"; 219*263b2ba5SJacek Lawrynowicz case IVPU_MMU_EVT_F_TLB_CONFLICT: 220*263b2ba5SJacek Lawrynowicz return "A TLB conflict"; 221*263b2ba5SJacek Lawrynowicz case IVPU_MMU_EVT_F_CFG_CONFLICT: 222*263b2ba5SJacek Lawrynowicz return "A configuration cache conflict"; 223*263b2ba5SJacek Lawrynowicz case IVPU_MMU_EVT_E_PAGE_REQUEST: 224*263b2ba5SJacek Lawrynowicz return "Page request hint from a client device"; 225*263b2ba5SJacek Lawrynowicz case IVPU_MMU_EVT_F_VMS_FETCH: 226*263b2ba5SJacek Lawrynowicz return "Fetch of VMS caused external abort"; 227*263b2ba5SJacek Lawrynowicz default: 228*263b2ba5SJacek Lawrynowicz return "Unknown CMDQ command"; 229*263b2ba5SJacek Lawrynowicz } 230*263b2ba5SJacek Lawrynowicz } 231*263b2ba5SJacek Lawrynowicz 232*263b2ba5SJacek Lawrynowicz static void ivpu_mmu_config_check(struct ivpu_device *vdev) 233*263b2ba5SJacek Lawrynowicz { 234*263b2ba5SJacek Lawrynowicz u32 val_ref; 235*263b2ba5SJacek Lawrynowicz u32 val; 236*263b2ba5SJacek Lawrynowicz 237*263b2ba5SJacek Lawrynowicz if (ivpu_is_simics(vdev)) 238*263b2ba5SJacek Lawrynowicz val_ref = IVPU_MMU_IDR0_REF_SIMICS; 239*263b2ba5SJacek Lawrynowicz else 240*263b2ba5SJacek Lawrynowicz val_ref = IVPU_MMU_IDR0_REF; 241*263b2ba5SJacek Lawrynowicz 242*263b2ba5SJacek Lawrynowicz val = REGV_RD32(MTL_VPU_HOST_MMU_IDR0); 243*263b2ba5SJacek Lawrynowicz if (val != val_ref) 244*263b2ba5SJacek Lawrynowicz ivpu_dbg(vdev, MMU, "IDR0 0x%x != IDR0_REF 0x%x\n", val, val_ref); 245*263b2ba5SJacek Lawrynowicz 246*263b2ba5SJacek Lawrynowicz val = REGV_RD32(MTL_VPU_HOST_MMU_IDR1); 247*263b2ba5SJacek Lawrynowicz if (val != IVPU_MMU_IDR1_REF) 248*263b2ba5SJacek Lawrynowicz ivpu_dbg(vdev, MMU, "IDR1 0x%x != IDR1_REF 0x%x\n", val, IVPU_MMU_IDR1_REF); 249*263b2ba5SJacek Lawrynowicz 250*263b2ba5SJacek Lawrynowicz val = REGV_RD32(MTL_VPU_HOST_MMU_IDR3); 251*263b2ba5SJacek Lawrynowicz if (val != IVPU_MMU_IDR3_REF) 252*263b2ba5SJacek Lawrynowicz ivpu_dbg(vdev, MMU, "IDR3 0x%x != IDR3_REF 0x%x\n", val, IVPU_MMU_IDR3_REF); 253*263b2ba5SJacek Lawrynowicz 254*263b2ba5SJacek Lawrynowicz if (ivpu_is_simics(vdev)) 255*263b2ba5SJacek Lawrynowicz val_ref = IVPU_MMU_IDR5_REF_SIMICS; 256*263b2ba5SJacek Lawrynowicz else if (ivpu_is_fpga(vdev)) 257*263b2ba5SJacek Lawrynowicz val_ref = IVPU_MMU_IDR5_REF_FPGA; 258*263b2ba5SJacek Lawrynowicz else 259*263b2ba5SJacek Lawrynowicz val_ref = IVPU_MMU_IDR5_REF; 260*263b2ba5SJacek Lawrynowicz 261*263b2ba5SJacek Lawrynowicz val = REGV_RD32(MTL_VPU_HOST_MMU_IDR5); 262*263b2ba5SJacek Lawrynowicz if (val != val_ref) 263*263b2ba5SJacek Lawrynowicz ivpu_dbg(vdev, MMU, "IDR5 0x%x != IDR5_REF 0x%x\n", val, val_ref); 264*263b2ba5SJacek Lawrynowicz } 265*263b2ba5SJacek Lawrynowicz 266*263b2ba5SJacek Lawrynowicz static int ivpu_mmu_cdtab_alloc(struct ivpu_device *vdev) 267*263b2ba5SJacek Lawrynowicz { 268*263b2ba5SJacek Lawrynowicz struct ivpu_mmu_info *mmu = vdev->mmu; 269*263b2ba5SJacek Lawrynowicz struct ivpu_mmu_cdtab *cdtab = &mmu->cdtab; 270*263b2ba5SJacek Lawrynowicz size_t size = IVPU_MMU_CDTAB_ENT_COUNT * IVPU_MMU_CDTAB_ENT_SIZE; 271*263b2ba5SJacek Lawrynowicz 272*263b2ba5SJacek Lawrynowicz cdtab->base = dmam_alloc_coherent(vdev->drm.dev, size, &cdtab->dma, GFP_KERNEL); 273*263b2ba5SJacek Lawrynowicz if (!cdtab->base) 274*263b2ba5SJacek Lawrynowicz return -ENOMEM; 275*263b2ba5SJacek Lawrynowicz 276*263b2ba5SJacek Lawrynowicz ivpu_dbg(vdev, MMU, "CDTAB alloc: dma=%pad size=%zu\n", &cdtab->dma, size); 277*263b2ba5SJacek Lawrynowicz 278*263b2ba5SJacek Lawrynowicz return 0; 279*263b2ba5SJacek Lawrynowicz } 280*263b2ba5SJacek Lawrynowicz 281*263b2ba5SJacek Lawrynowicz static int ivpu_mmu_strtab_alloc(struct ivpu_device *vdev) 282*263b2ba5SJacek Lawrynowicz { 283*263b2ba5SJacek Lawrynowicz struct ivpu_mmu_info *mmu = vdev->mmu; 284*263b2ba5SJacek Lawrynowicz struct ivpu_mmu_strtab *strtab = &mmu->strtab; 285*263b2ba5SJacek Lawrynowicz size_t size = IVPU_MMU_STRTAB_ENT_COUNT * IVPU_MMU_STRTAB_ENT_SIZE; 286*263b2ba5SJacek Lawrynowicz 287*263b2ba5SJacek Lawrynowicz strtab->base = dmam_alloc_coherent(vdev->drm.dev, size, &strtab->dma, GFP_KERNEL); 288*263b2ba5SJacek Lawrynowicz if (!strtab->base) 289*263b2ba5SJacek Lawrynowicz return -ENOMEM; 290*263b2ba5SJacek Lawrynowicz 291*263b2ba5SJacek Lawrynowicz strtab->base_cfg = IVPU_MMU_STRTAB_CFG; 292*263b2ba5SJacek Lawrynowicz strtab->dma_q = IVPU_MMU_STRTAB_BASE_RA; 293*263b2ba5SJacek Lawrynowicz strtab->dma_q |= strtab->dma & IVPU_MMU_STRTAB_BASE_ADDR_MASK; 294*263b2ba5SJacek Lawrynowicz 295*263b2ba5SJacek Lawrynowicz ivpu_dbg(vdev, MMU, "STRTAB alloc: dma=%pad dma_q=%pad size=%zu\n", 296*263b2ba5SJacek Lawrynowicz &strtab->dma, &strtab->dma_q, size); 297*263b2ba5SJacek Lawrynowicz 298*263b2ba5SJacek Lawrynowicz return 0; 299*263b2ba5SJacek Lawrynowicz } 300*263b2ba5SJacek Lawrynowicz 301*263b2ba5SJacek Lawrynowicz static int ivpu_mmu_cmdq_alloc(struct ivpu_device *vdev) 302*263b2ba5SJacek Lawrynowicz { 303*263b2ba5SJacek Lawrynowicz struct ivpu_mmu_info *mmu = vdev->mmu; 304*263b2ba5SJacek Lawrynowicz struct ivpu_mmu_queue *q = &mmu->cmdq; 305*263b2ba5SJacek Lawrynowicz 306*263b2ba5SJacek Lawrynowicz q->base = dmam_alloc_coherent(vdev->drm.dev, IVPU_MMU_CMDQ_SIZE, &q->dma, GFP_KERNEL); 307*263b2ba5SJacek Lawrynowicz if (!q->base) 308*263b2ba5SJacek Lawrynowicz return -ENOMEM; 309*263b2ba5SJacek Lawrynowicz 310*263b2ba5SJacek Lawrynowicz q->dma_q = IVPU_MMU_Q_BASE_RWA; 311*263b2ba5SJacek Lawrynowicz q->dma_q |= q->dma & IVPU_MMU_Q_BASE_ADDR_MASK; 312*263b2ba5SJacek Lawrynowicz q->dma_q |= IVPU_MMU_Q_COUNT_LOG2; 313*263b2ba5SJacek Lawrynowicz 314*263b2ba5SJacek Lawrynowicz ivpu_dbg(vdev, MMU, "CMDQ alloc: dma=%pad dma_q=%pad size=%u\n", 315*263b2ba5SJacek Lawrynowicz &q->dma, &q->dma_q, IVPU_MMU_CMDQ_SIZE); 316*263b2ba5SJacek Lawrynowicz 317*263b2ba5SJacek Lawrynowicz return 0; 318*263b2ba5SJacek Lawrynowicz } 319*263b2ba5SJacek Lawrynowicz 320*263b2ba5SJacek Lawrynowicz static int ivpu_mmu_evtq_alloc(struct ivpu_device *vdev) 321*263b2ba5SJacek Lawrynowicz { 322*263b2ba5SJacek Lawrynowicz struct ivpu_mmu_info *mmu = vdev->mmu; 323*263b2ba5SJacek Lawrynowicz struct ivpu_mmu_queue *q = &mmu->evtq; 324*263b2ba5SJacek Lawrynowicz 325*263b2ba5SJacek Lawrynowicz q->base = dmam_alloc_coherent(vdev->drm.dev, IVPU_MMU_EVTQ_SIZE, &q->dma, GFP_KERNEL); 326*263b2ba5SJacek Lawrynowicz if (!q->base) 327*263b2ba5SJacek Lawrynowicz return -ENOMEM; 328*263b2ba5SJacek Lawrynowicz 329*263b2ba5SJacek Lawrynowicz q->dma_q = IVPU_MMU_Q_BASE_RWA; 330*263b2ba5SJacek Lawrynowicz q->dma_q |= q->dma & IVPU_MMU_Q_BASE_ADDR_MASK; 331*263b2ba5SJacek Lawrynowicz q->dma_q |= IVPU_MMU_Q_COUNT_LOG2; 332*263b2ba5SJacek Lawrynowicz 333*263b2ba5SJacek Lawrynowicz ivpu_dbg(vdev, MMU, "EVTQ alloc: dma=%pad dma_q=%pad size=%u\n", 334*263b2ba5SJacek Lawrynowicz &q->dma, &q->dma_q, IVPU_MMU_EVTQ_SIZE); 335*263b2ba5SJacek Lawrynowicz 336*263b2ba5SJacek Lawrynowicz return 0; 337*263b2ba5SJacek Lawrynowicz } 338*263b2ba5SJacek Lawrynowicz 339*263b2ba5SJacek Lawrynowicz static int ivpu_mmu_structs_alloc(struct ivpu_device *vdev) 340*263b2ba5SJacek Lawrynowicz { 341*263b2ba5SJacek Lawrynowicz int ret; 342*263b2ba5SJacek Lawrynowicz 343*263b2ba5SJacek Lawrynowicz ret = ivpu_mmu_cdtab_alloc(vdev); 344*263b2ba5SJacek Lawrynowicz if (ret) { 345*263b2ba5SJacek Lawrynowicz ivpu_err(vdev, "Failed to allocate cdtab: %d\n", ret); 346*263b2ba5SJacek Lawrynowicz return ret; 347*263b2ba5SJacek Lawrynowicz } 348*263b2ba5SJacek Lawrynowicz 349*263b2ba5SJacek Lawrynowicz ret = ivpu_mmu_strtab_alloc(vdev); 350*263b2ba5SJacek Lawrynowicz if (ret) { 351*263b2ba5SJacek Lawrynowicz ivpu_err(vdev, "Failed to allocate strtab: %d\n", ret); 352*263b2ba5SJacek Lawrynowicz return ret; 353*263b2ba5SJacek Lawrynowicz } 354*263b2ba5SJacek Lawrynowicz 355*263b2ba5SJacek Lawrynowicz ret = ivpu_mmu_cmdq_alloc(vdev); 356*263b2ba5SJacek Lawrynowicz if (ret) { 357*263b2ba5SJacek Lawrynowicz ivpu_err(vdev, "Failed to allocate cmdq: %d\n", ret); 358*263b2ba5SJacek Lawrynowicz return ret; 359*263b2ba5SJacek Lawrynowicz } 360*263b2ba5SJacek Lawrynowicz 361*263b2ba5SJacek Lawrynowicz ret = ivpu_mmu_evtq_alloc(vdev); 362*263b2ba5SJacek Lawrynowicz if (ret) 363*263b2ba5SJacek Lawrynowicz ivpu_err(vdev, "Failed to allocate evtq: %d\n", ret); 364*263b2ba5SJacek Lawrynowicz 365*263b2ba5SJacek Lawrynowicz return ret; 366*263b2ba5SJacek Lawrynowicz } 367*263b2ba5SJacek Lawrynowicz 368*263b2ba5SJacek Lawrynowicz static int ivpu_mmu_reg_write(struct ivpu_device *vdev, u32 reg, u32 val) 369*263b2ba5SJacek Lawrynowicz { 370*263b2ba5SJacek Lawrynowicz u32 reg_ack = reg + 4; /* ACK register is 4B after base register */ 371*263b2ba5SJacek Lawrynowicz u32 val_ack; 372*263b2ba5SJacek Lawrynowicz int ret; 373*263b2ba5SJacek Lawrynowicz 374*263b2ba5SJacek Lawrynowicz REGV_WR32(reg, val); 375*263b2ba5SJacek Lawrynowicz 376*263b2ba5SJacek Lawrynowicz ret = REGV_POLL(reg_ack, val_ack, (val == val_ack), IVPU_MMU_REG_TIMEOUT_US); 377*263b2ba5SJacek Lawrynowicz if (ret) 378*263b2ba5SJacek Lawrynowicz ivpu_err(vdev, "Failed to write register 0x%x\n", reg); 379*263b2ba5SJacek Lawrynowicz 380*263b2ba5SJacek Lawrynowicz return ret; 381*263b2ba5SJacek Lawrynowicz } 382*263b2ba5SJacek Lawrynowicz 383*263b2ba5SJacek Lawrynowicz static int ivpu_mmu_irqs_setup(struct ivpu_device *vdev) 384*263b2ba5SJacek Lawrynowicz { 385*263b2ba5SJacek Lawrynowicz u32 irq_ctrl = IVPU_MMU_IRQ_EVTQ_EN | IVPU_MMU_IRQ_GERROR_EN; 386*263b2ba5SJacek Lawrynowicz int ret; 387*263b2ba5SJacek Lawrynowicz 388*263b2ba5SJacek Lawrynowicz ret = ivpu_mmu_reg_write(vdev, MTL_VPU_HOST_MMU_IRQ_CTRL, 0); 389*263b2ba5SJacek Lawrynowicz if (ret) 390*263b2ba5SJacek Lawrynowicz return ret; 391*263b2ba5SJacek Lawrynowicz 392*263b2ba5SJacek Lawrynowicz return ivpu_mmu_reg_write(vdev, MTL_VPU_HOST_MMU_IRQ_CTRL, irq_ctrl); 393*263b2ba5SJacek Lawrynowicz } 394*263b2ba5SJacek Lawrynowicz 395*263b2ba5SJacek Lawrynowicz static int ivpu_mmu_cmdq_wait_for_cons(struct ivpu_device *vdev) 396*263b2ba5SJacek Lawrynowicz { 397*263b2ba5SJacek Lawrynowicz struct ivpu_mmu_queue *cmdq = &vdev->mmu->cmdq; 398*263b2ba5SJacek Lawrynowicz 399*263b2ba5SJacek Lawrynowicz return REGV_POLL(MTL_VPU_HOST_MMU_CMDQ_CONS, cmdq->cons, (cmdq->prod == cmdq->cons), 400*263b2ba5SJacek Lawrynowicz IVPU_MMU_QUEUE_TIMEOUT_US); 401*263b2ba5SJacek Lawrynowicz } 402*263b2ba5SJacek Lawrynowicz 403*263b2ba5SJacek Lawrynowicz static int ivpu_mmu_cmdq_cmd_write(struct ivpu_device *vdev, const char *name, u64 data0, u64 data1) 404*263b2ba5SJacek Lawrynowicz { 405*263b2ba5SJacek Lawrynowicz struct ivpu_mmu_queue *q = &vdev->mmu->cmdq; 406*263b2ba5SJacek Lawrynowicz u64 *queue_buffer = q->base; 407*263b2ba5SJacek Lawrynowicz int idx = IVPU_MMU_Q_IDX(q->prod) * (IVPU_MMU_CMDQ_CMD_SIZE / sizeof(*queue_buffer)); 408*263b2ba5SJacek Lawrynowicz 409*263b2ba5SJacek Lawrynowicz if (!CIRC_SPACE(IVPU_MMU_Q_IDX(q->prod), IVPU_MMU_Q_IDX(q->cons), IVPU_MMU_Q_COUNT)) { 410*263b2ba5SJacek Lawrynowicz ivpu_err(vdev, "Failed to write MMU CMD %s\n", name); 411*263b2ba5SJacek Lawrynowicz return -EBUSY; 412*263b2ba5SJacek Lawrynowicz } 413*263b2ba5SJacek Lawrynowicz 414*263b2ba5SJacek Lawrynowicz queue_buffer[idx] = data0; 415*263b2ba5SJacek Lawrynowicz queue_buffer[idx + 1] = data1; 416*263b2ba5SJacek Lawrynowicz q->prod = (q->prod + 1) & IVPU_MMU_Q_WRAP_MASK; 417*263b2ba5SJacek Lawrynowicz 418*263b2ba5SJacek Lawrynowicz ivpu_dbg(vdev, MMU, "CMD write: %s data: 0x%llx 0x%llx\n", name, data0, data1); 419*263b2ba5SJacek Lawrynowicz 420*263b2ba5SJacek Lawrynowicz return 0; 421*263b2ba5SJacek Lawrynowicz } 422*263b2ba5SJacek Lawrynowicz 423*263b2ba5SJacek Lawrynowicz static int ivpu_mmu_cmdq_sync(struct ivpu_device *vdev) 424*263b2ba5SJacek Lawrynowicz { 425*263b2ba5SJacek Lawrynowicz struct ivpu_mmu_queue *q = &vdev->mmu->cmdq; 426*263b2ba5SJacek Lawrynowicz u64 val; 427*263b2ba5SJacek Lawrynowicz int ret; 428*263b2ba5SJacek Lawrynowicz 429*263b2ba5SJacek Lawrynowicz val = FIELD_PREP(IVPU_MMU_CMD_OPCODE, CMD_SYNC) | 430*263b2ba5SJacek Lawrynowicz FIELD_PREP(IVPU_MMU_CMD_SYNC_0_CS, 0x2) | 431*263b2ba5SJacek Lawrynowicz FIELD_PREP(IVPU_MMU_CMD_SYNC_0_MSH, 0x3) | 432*263b2ba5SJacek Lawrynowicz FIELD_PREP(IVPU_MMU_CMD_SYNC_0_MSI_ATTR, 0xf); 433*263b2ba5SJacek Lawrynowicz 434*263b2ba5SJacek Lawrynowicz ret = ivpu_mmu_cmdq_cmd_write(vdev, "SYNC", val, 0); 435*263b2ba5SJacek Lawrynowicz if (ret) 436*263b2ba5SJacek Lawrynowicz return ret; 437*263b2ba5SJacek Lawrynowicz 438*263b2ba5SJacek Lawrynowicz clflush_cache_range(q->base, IVPU_MMU_CMDQ_SIZE); 439*263b2ba5SJacek Lawrynowicz REGV_WR32(MTL_VPU_HOST_MMU_CMDQ_PROD, q->prod); 440*263b2ba5SJacek Lawrynowicz 441*263b2ba5SJacek Lawrynowicz ret = ivpu_mmu_cmdq_wait_for_cons(vdev); 442*263b2ba5SJacek Lawrynowicz if (ret) 443*263b2ba5SJacek Lawrynowicz ivpu_err(vdev, "Timed out waiting for consumer: %d\n", ret); 444*263b2ba5SJacek Lawrynowicz 445*263b2ba5SJacek Lawrynowicz return ret; 446*263b2ba5SJacek Lawrynowicz } 447*263b2ba5SJacek Lawrynowicz 448*263b2ba5SJacek Lawrynowicz static int ivpu_mmu_cmdq_write_cfgi_all(struct ivpu_device *vdev) 449*263b2ba5SJacek Lawrynowicz { 450*263b2ba5SJacek Lawrynowicz u64 data0 = FIELD_PREP(IVPU_MMU_CMD_OPCODE, CMD_CFGI_ALL); 451*263b2ba5SJacek Lawrynowicz u64 data1 = FIELD_PREP(IVPU_MMU_CMD_CFGI_1_RANGE, 0x1f); 452*263b2ba5SJacek Lawrynowicz 453*263b2ba5SJacek Lawrynowicz return ivpu_mmu_cmdq_cmd_write(vdev, "CFGI_ALL", data0, data1); 454*263b2ba5SJacek Lawrynowicz } 455*263b2ba5SJacek Lawrynowicz 456*263b2ba5SJacek Lawrynowicz static int ivpu_mmu_cmdq_write_tlbi_nh_asid(struct ivpu_device *vdev, u16 ssid) 457*263b2ba5SJacek Lawrynowicz { 458*263b2ba5SJacek Lawrynowicz u64 val = FIELD_PREP(IVPU_MMU_CMD_OPCODE, CMD_TLBI_NH_ASID) | 459*263b2ba5SJacek Lawrynowicz FIELD_PREP(IVPU_MMU_CMD_TLBI_0_ASID, ssid); 460*263b2ba5SJacek Lawrynowicz 461*263b2ba5SJacek Lawrynowicz return ivpu_mmu_cmdq_cmd_write(vdev, "TLBI_NH_ASID", val, 0); 462*263b2ba5SJacek Lawrynowicz } 463*263b2ba5SJacek Lawrynowicz 464*263b2ba5SJacek Lawrynowicz static int ivpu_mmu_cmdq_write_tlbi_nsnh_all(struct ivpu_device *vdev) 465*263b2ba5SJacek Lawrynowicz { 466*263b2ba5SJacek Lawrynowicz u64 val = FIELD_PREP(IVPU_MMU_CMD_OPCODE, CMD_TLBI_NSNH_ALL); 467*263b2ba5SJacek Lawrynowicz 468*263b2ba5SJacek Lawrynowicz return ivpu_mmu_cmdq_cmd_write(vdev, "TLBI_NSNH_ALL", val, 0); 469*263b2ba5SJacek Lawrynowicz } 470*263b2ba5SJacek Lawrynowicz 471*263b2ba5SJacek Lawrynowicz static int ivpu_mmu_reset(struct ivpu_device *vdev) 472*263b2ba5SJacek Lawrynowicz { 473*263b2ba5SJacek Lawrynowicz struct ivpu_mmu_info *mmu = vdev->mmu; 474*263b2ba5SJacek Lawrynowicz u32 val; 475*263b2ba5SJacek Lawrynowicz int ret; 476*263b2ba5SJacek Lawrynowicz 477*263b2ba5SJacek Lawrynowicz memset(mmu->cmdq.base, 0, IVPU_MMU_CMDQ_SIZE); 478*263b2ba5SJacek Lawrynowicz clflush_cache_range(mmu->cmdq.base, IVPU_MMU_CMDQ_SIZE); 479*263b2ba5SJacek Lawrynowicz mmu->cmdq.prod = 0; 480*263b2ba5SJacek Lawrynowicz mmu->cmdq.cons = 0; 481*263b2ba5SJacek Lawrynowicz 482*263b2ba5SJacek Lawrynowicz memset(mmu->evtq.base, 0, IVPU_MMU_EVTQ_SIZE); 483*263b2ba5SJacek Lawrynowicz clflush_cache_range(mmu->evtq.base, IVPU_MMU_EVTQ_SIZE); 484*263b2ba5SJacek Lawrynowicz mmu->evtq.prod = 0; 485*263b2ba5SJacek Lawrynowicz mmu->evtq.cons = 0; 486*263b2ba5SJacek Lawrynowicz 487*263b2ba5SJacek Lawrynowicz ret = ivpu_mmu_reg_write(vdev, MTL_VPU_HOST_MMU_CR0, 0); 488*263b2ba5SJacek Lawrynowicz if (ret) 489*263b2ba5SJacek Lawrynowicz return ret; 490*263b2ba5SJacek Lawrynowicz 491*263b2ba5SJacek Lawrynowicz val = FIELD_PREP(IVPU_MMU_CR1_TABLE_SH, IVPU_MMU_SH_ISH) | 492*263b2ba5SJacek Lawrynowicz FIELD_PREP(IVPU_MMU_CR1_TABLE_OC, IVPU_MMU_CACHE_WB) | 493*263b2ba5SJacek Lawrynowicz FIELD_PREP(IVPU_MMU_CR1_TABLE_IC, IVPU_MMU_CACHE_WB) | 494*263b2ba5SJacek Lawrynowicz FIELD_PREP(IVPU_MMU_CR1_QUEUE_SH, IVPU_MMU_SH_ISH) | 495*263b2ba5SJacek Lawrynowicz FIELD_PREP(IVPU_MMU_CR1_QUEUE_OC, IVPU_MMU_CACHE_WB) | 496*263b2ba5SJacek Lawrynowicz FIELD_PREP(IVPU_MMU_CR1_QUEUE_IC, IVPU_MMU_CACHE_WB); 497*263b2ba5SJacek Lawrynowicz REGV_WR32(MTL_VPU_HOST_MMU_CR1, val); 498*263b2ba5SJacek Lawrynowicz 499*263b2ba5SJacek Lawrynowicz REGV_WR64(MTL_VPU_HOST_MMU_STRTAB_BASE, mmu->strtab.dma_q); 500*263b2ba5SJacek Lawrynowicz REGV_WR32(MTL_VPU_HOST_MMU_STRTAB_BASE_CFG, mmu->strtab.base_cfg); 501*263b2ba5SJacek Lawrynowicz 502*263b2ba5SJacek Lawrynowicz REGV_WR64(MTL_VPU_HOST_MMU_CMDQ_BASE, mmu->cmdq.dma_q); 503*263b2ba5SJacek Lawrynowicz REGV_WR32(MTL_VPU_HOST_MMU_CMDQ_PROD, 0); 504*263b2ba5SJacek Lawrynowicz REGV_WR32(MTL_VPU_HOST_MMU_CMDQ_CONS, 0); 505*263b2ba5SJacek Lawrynowicz 506*263b2ba5SJacek Lawrynowicz val = IVPU_MMU_CR0_CMDQEN; 507*263b2ba5SJacek Lawrynowicz ret = ivpu_mmu_reg_write(vdev, MTL_VPU_HOST_MMU_CR0, val); 508*263b2ba5SJacek Lawrynowicz if (ret) 509*263b2ba5SJacek Lawrynowicz return ret; 510*263b2ba5SJacek Lawrynowicz 511*263b2ba5SJacek Lawrynowicz ret = ivpu_mmu_cmdq_write_cfgi_all(vdev); 512*263b2ba5SJacek Lawrynowicz if (ret) 513*263b2ba5SJacek Lawrynowicz return ret; 514*263b2ba5SJacek Lawrynowicz 515*263b2ba5SJacek Lawrynowicz ret = ivpu_mmu_cmdq_write_tlbi_nsnh_all(vdev); 516*263b2ba5SJacek Lawrynowicz if (ret) 517*263b2ba5SJacek Lawrynowicz return ret; 518*263b2ba5SJacek Lawrynowicz 519*263b2ba5SJacek Lawrynowicz ret = ivpu_mmu_cmdq_sync(vdev); 520*263b2ba5SJacek Lawrynowicz if (ret) 521*263b2ba5SJacek Lawrynowicz return ret; 522*263b2ba5SJacek Lawrynowicz 523*263b2ba5SJacek Lawrynowicz REGV_WR64(MTL_VPU_HOST_MMU_EVTQ_BASE, mmu->evtq.dma_q); 524*263b2ba5SJacek Lawrynowicz REGV_WR32(MTL_VPU_HOST_MMU_EVTQ_PROD_SEC, 0); 525*263b2ba5SJacek Lawrynowicz REGV_WR32(MTL_VPU_HOST_MMU_EVTQ_CONS_SEC, 0); 526*263b2ba5SJacek Lawrynowicz 527*263b2ba5SJacek Lawrynowicz val |= IVPU_MMU_CR0_EVTQEN; 528*263b2ba5SJacek Lawrynowicz ret = ivpu_mmu_reg_write(vdev, MTL_VPU_HOST_MMU_CR0, val); 529*263b2ba5SJacek Lawrynowicz if (ret) 530*263b2ba5SJacek Lawrynowicz return ret; 531*263b2ba5SJacek Lawrynowicz 532*263b2ba5SJacek Lawrynowicz val |= IVPU_MMU_CR0_ATSCHK; 533*263b2ba5SJacek Lawrynowicz ret = ivpu_mmu_reg_write(vdev, MTL_VPU_HOST_MMU_CR0, val); 534*263b2ba5SJacek Lawrynowicz if (ret) 535*263b2ba5SJacek Lawrynowicz return ret; 536*263b2ba5SJacek Lawrynowicz 537*263b2ba5SJacek Lawrynowicz ret = ivpu_mmu_irqs_setup(vdev); 538*263b2ba5SJacek Lawrynowicz if (ret) 539*263b2ba5SJacek Lawrynowicz return ret; 540*263b2ba5SJacek Lawrynowicz 541*263b2ba5SJacek Lawrynowicz val |= IVPU_MMU_CR0_SMMUEN; 542*263b2ba5SJacek Lawrynowicz return ivpu_mmu_reg_write(vdev, MTL_VPU_HOST_MMU_CR0, val); 543*263b2ba5SJacek Lawrynowicz } 544*263b2ba5SJacek Lawrynowicz 545*263b2ba5SJacek Lawrynowicz static void ivpu_mmu_strtab_link_cd(struct ivpu_device *vdev, u32 sid) 546*263b2ba5SJacek Lawrynowicz { 547*263b2ba5SJacek Lawrynowicz struct ivpu_mmu_info *mmu = vdev->mmu; 548*263b2ba5SJacek Lawrynowicz struct ivpu_mmu_strtab *strtab = &mmu->strtab; 549*263b2ba5SJacek Lawrynowicz struct ivpu_mmu_cdtab *cdtab = &mmu->cdtab; 550*263b2ba5SJacek Lawrynowicz u64 *entry = strtab->base + (sid * IVPU_MMU_STRTAB_ENT_SIZE); 551*263b2ba5SJacek Lawrynowicz u64 str[2]; 552*263b2ba5SJacek Lawrynowicz 553*263b2ba5SJacek Lawrynowicz str[0] = FIELD_PREP(IVPU_MMU_STE_0_CFG, IVPU_MMU_STE_0_CFG_S1_TRANS) | 554*263b2ba5SJacek Lawrynowicz FIELD_PREP(IVPU_MMU_STE_0_S1CDMAX, IVPU_MMU_CDTAB_ENT_COUNT_LOG2) | 555*263b2ba5SJacek Lawrynowicz FIELD_PREP(IVPU_MMU_STE_0_S1FMT, IVPU_MMU_STE_0_S1FMT_LINEAR) | 556*263b2ba5SJacek Lawrynowicz IVPU_MMU_STE_0_V | 557*263b2ba5SJacek Lawrynowicz (cdtab->dma & IVPU_MMU_STE_0_S1CTXPTR_MASK); 558*263b2ba5SJacek Lawrynowicz 559*263b2ba5SJacek Lawrynowicz str[1] = FIELD_PREP(IVPU_MMU_STE_1_S1DSS, IVPU_MMU_STE_1_S1DSS_TERMINATE) | 560*263b2ba5SJacek Lawrynowicz FIELD_PREP(IVPU_MMU_STE_1_S1CIR, IVPU_MMU_STE_1_S1C_CACHE_NC) | 561*263b2ba5SJacek Lawrynowicz FIELD_PREP(IVPU_MMU_STE_1_S1COR, IVPU_MMU_STE_1_S1C_CACHE_NC) | 562*263b2ba5SJacek Lawrynowicz FIELD_PREP(IVPU_MMU_STE_1_S1CSH, IVPU_MMU_SH_NSH) | 563*263b2ba5SJacek Lawrynowicz FIELD_PREP(IVPU_MMU_STE_1_PRIVCFG, IVPU_MMU_STE_1_PRIVCFG_UNPRIV) | 564*263b2ba5SJacek Lawrynowicz FIELD_PREP(IVPU_MMU_STE_1_INSTCFG, IVPU_MMU_STE_1_INSTCFG_DATA) | 565*263b2ba5SJacek Lawrynowicz FIELD_PREP(IVPU_MMU_STE_1_STRW, IVPU_MMU_STE_1_STRW_NSEL1) | 566*263b2ba5SJacek Lawrynowicz FIELD_PREP(IVPU_MMU_STE_1_CONT, IVPU_MMU_STRTAB_CFG_LOG2SIZE) | 567*263b2ba5SJacek Lawrynowicz IVPU_MMU_STE_1_MEV | 568*263b2ba5SJacek Lawrynowicz IVPU_MMU_STE_1_S1STALLD; 569*263b2ba5SJacek Lawrynowicz 570*263b2ba5SJacek Lawrynowicz WRITE_ONCE(entry[1], str[1]); 571*263b2ba5SJacek Lawrynowicz WRITE_ONCE(entry[0], str[0]); 572*263b2ba5SJacek Lawrynowicz 573*263b2ba5SJacek Lawrynowicz clflush_cache_range(entry, IVPU_MMU_STRTAB_ENT_SIZE); 574*263b2ba5SJacek Lawrynowicz 575*263b2ba5SJacek Lawrynowicz ivpu_dbg(vdev, MMU, "STRTAB write entry (SSID=%u): 0x%llx, 0x%llx\n", sid, str[0], str[1]); 576*263b2ba5SJacek Lawrynowicz } 577*263b2ba5SJacek Lawrynowicz 578*263b2ba5SJacek Lawrynowicz static int ivpu_mmu_strtab_init(struct ivpu_device *vdev) 579*263b2ba5SJacek Lawrynowicz { 580*263b2ba5SJacek Lawrynowicz ivpu_mmu_strtab_link_cd(vdev, IVPU_MMU_STREAM_ID0); 581*263b2ba5SJacek Lawrynowicz ivpu_mmu_strtab_link_cd(vdev, IVPU_MMU_STREAM_ID3); 582*263b2ba5SJacek Lawrynowicz 583*263b2ba5SJacek Lawrynowicz return 0; 584*263b2ba5SJacek Lawrynowicz } 585*263b2ba5SJacek Lawrynowicz 586*263b2ba5SJacek Lawrynowicz int ivpu_mmu_invalidate_tlb(struct ivpu_device *vdev, u16 ssid) 587*263b2ba5SJacek Lawrynowicz { 588*263b2ba5SJacek Lawrynowicz struct ivpu_mmu_info *mmu = vdev->mmu; 589*263b2ba5SJacek Lawrynowicz int ret; 590*263b2ba5SJacek Lawrynowicz 591*263b2ba5SJacek Lawrynowicz ret = mutex_lock_interruptible(&mmu->lock); 592*263b2ba5SJacek Lawrynowicz if (ret) 593*263b2ba5SJacek Lawrynowicz return ret; 594*263b2ba5SJacek Lawrynowicz 595*263b2ba5SJacek Lawrynowicz if (!mmu->on) { 596*263b2ba5SJacek Lawrynowicz ret = 0; 597*263b2ba5SJacek Lawrynowicz goto unlock; 598*263b2ba5SJacek Lawrynowicz } 599*263b2ba5SJacek Lawrynowicz 600*263b2ba5SJacek Lawrynowicz ret = ivpu_mmu_cmdq_write_tlbi_nh_asid(vdev, ssid); 601*263b2ba5SJacek Lawrynowicz if (ret) 602*263b2ba5SJacek Lawrynowicz goto unlock; 603*263b2ba5SJacek Lawrynowicz 604*263b2ba5SJacek Lawrynowicz ret = ivpu_mmu_cmdq_sync(vdev); 605*263b2ba5SJacek Lawrynowicz unlock: 606*263b2ba5SJacek Lawrynowicz mutex_unlock(&mmu->lock); 607*263b2ba5SJacek Lawrynowicz return ret; 608*263b2ba5SJacek Lawrynowicz } 609*263b2ba5SJacek Lawrynowicz 610*263b2ba5SJacek Lawrynowicz static int ivpu_mmu_cd_add(struct ivpu_device *vdev, u32 ssid, u64 cd_dma) 611*263b2ba5SJacek Lawrynowicz { 612*263b2ba5SJacek Lawrynowicz struct ivpu_mmu_info *mmu = vdev->mmu; 613*263b2ba5SJacek Lawrynowicz struct ivpu_mmu_cdtab *cdtab = &mmu->cdtab; 614*263b2ba5SJacek Lawrynowicz u64 *entry; 615*263b2ba5SJacek Lawrynowicz u64 cd[4]; 616*263b2ba5SJacek Lawrynowicz int ret; 617*263b2ba5SJacek Lawrynowicz 618*263b2ba5SJacek Lawrynowicz if (ssid > IVPU_MMU_CDTAB_ENT_COUNT) 619*263b2ba5SJacek Lawrynowicz return -EINVAL; 620*263b2ba5SJacek Lawrynowicz 621*263b2ba5SJacek Lawrynowicz entry = cdtab->base + (ssid * IVPU_MMU_CDTAB_ENT_SIZE); 622*263b2ba5SJacek Lawrynowicz 623*263b2ba5SJacek Lawrynowicz if (cd_dma != 0) { 624*263b2ba5SJacek Lawrynowicz cd[0] = FIELD_PREP(IVPU_MMU_CD_0_TCR_T0SZ, 26) | 625*263b2ba5SJacek Lawrynowicz FIELD_PREP(IVPU_MMU_CD_0_TCR_TG0, 0) | 626*263b2ba5SJacek Lawrynowicz FIELD_PREP(IVPU_MMU_CD_0_TCR_IRGN0, 0) | 627*263b2ba5SJacek Lawrynowicz FIELD_PREP(IVPU_MMU_CD_0_TCR_ORGN0, 0) | 628*263b2ba5SJacek Lawrynowicz FIELD_PREP(IVPU_MMU_CD_0_TCR_SH0, 0) | 629*263b2ba5SJacek Lawrynowicz FIELD_PREP(IVPU_MMU_CD_0_TCR_IPS, 3) | 630*263b2ba5SJacek Lawrynowicz FIELD_PREP(IVPU_MMU_CD_0_ASID, ssid) | 631*263b2ba5SJacek Lawrynowicz IVPU_MMU_CD_0_TCR_EPD1 | 632*263b2ba5SJacek Lawrynowicz IVPU_MMU_CD_0_AA64 | 633*263b2ba5SJacek Lawrynowicz IVPU_MMU_CD_0_R | 634*263b2ba5SJacek Lawrynowicz IVPU_MMU_CD_0_ASET | 635*263b2ba5SJacek Lawrynowicz IVPU_MMU_CD_0_V; 636*263b2ba5SJacek Lawrynowicz cd[1] = cd_dma & IVPU_MMU_CD_1_TTB0_MASK; 637*263b2ba5SJacek Lawrynowicz cd[2] = 0; 638*263b2ba5SJacek Lawrynowicz cd[3] = 0x0000000000007444; 639*263b2ba5SJacek Lawrynowicz 640*263b2ba5SJacek Lawrynowicz /* For global context generate memory fault on VPU */ 641*263b2ba5SJacek Lawrynowicz if (ssid == IVPU_GLOBAL_CONTEXT_MMU_SSID) 642*263b2ba5SJacek Lawrynowicz cd[0] |= IVPU_MMU_CD_0_A; 643*263b2ba5SJacek Lawrynowicz } else { 644*263b2ba5SJacek Lawrynowicz memset(cd, 0, sizeof(cd)); 645*263b2ba5SJacek Lawrynowicz } 646*263b2ba5SJacek Lawrynowicz 647*263b2ba5SJacek Lawrynowicz WRITE_ONCE(entry[1], cd[1]); 648*263b2ba5SJacek Lawrynowicz WRITE_ONCE(entry[2], cd[2]); 649*263b2ba5SJacek Lawrynowicz WRITE_ONCE(entry[3], cd[3]); 650*263b2ba5SJacek Lawrynowicz WRITE_ONCE(entry[0], cd[0]); 651*263b2ba5SJacek Lawrynowicz 652*263b2ba5SJacek Lawrynowicz clflush_cache_range(entry, IVPU_MMU_CDTAB_ENT_SIZE); 653*263b2ba5SJacek Lawrynowicz 654*263b2ba5SJacek Lawrynowicz ivpu_dbg(vdev, MMU, "CDTAB %s entry (SSID=%u, dma=%pad): 0x%llx, 0x%llx, 0x%llx, 0x%llx\n", 655*263b2ba5SJacek Lawrynowicz cd_dma ? "write" : "clear", ssid, &cd_dma, cd[0], cd[1], cd[2], cd[3]); 656*263b2ba5SJacek Lawrynowicz 657*263b2ba5SJacek Lawrynowicz ret = mutex_lock_interruptible(&mmu->lock); 658*263b2ba5SJacek Lawrynowicz if (ret) 659*263b2ba5SJacek Lawrynowicz return ret; 660*263b2ba5SJacek Lawrynowicz 661*263b2ba5SJacek Lawrynowicz if (!mmu->on) { 662*263b2ba5SJacek Lawrynowicz ret = 0; 663*263b2ba5SJacek Lawrynowicz goto unlock; 664*263b2ba5SJacek Lawrynowicz } 665*263b2ba5SJacek Lawrynowicz 666*263b2ba5SJacek Lawrynowicz ret = ivpu_mmu_cmdq_write_cfgi_all(vdev); 667*263b2ba5SJacek Lawrynowicz if (ret) 668*263b2ba5SJacek Lawrynowicz goto unlock; 669*263b2ba5SJacek Lawrynowicz 670*263b2ba5SJacek Lawrynowicz ret = ivpu_mmu_cmdq_sync(vdev); 671*263b2ba5SJacek Lawrynowicz unlock: 672*263b2ba5SJacek Lawrynowicz mutex_unlock(&mmu->lock); 673*263b2ba5SJacek Lawrynowicz return ret; 674*263b2ba5SJacek Lawrynowicz } 675*263b2ba5SJacek Lawrynowicz 676*263b2ba5SJacek Lawrynowicz static int ivpu_mmu_cd_add_gbl(struct ivpu_device *vdev) 677*263b2ba5SJacek Lawrynowicz { 678*263b2ba5SJacek Lawrynowicz int ret; 679*263b2ba5SJacek Lawrynowicz 680*263b2ba5SJacek Lawrynowicz ret = ivpu_mmu_cd_add(vdev, 0, vdev->gctx.pgtable.pgd_dma); 681*263b2ba5SJacek Lawrynowicz if (ret) 682*263b2ba5SJacek Lawrynowicz ivpu_err(vdev, "Failed to add global CD entry: %d\n", ret); 683*263b2ba5SJacek Lawrynowicz 684*263b2ba5SJacek Lawrynowicz return ret; 685*263b2ba5SJacek Lawrynowicz } 686*263b2ba5SJacek Lawrynowicz 687*263b2ba5SJacek Lawrynowicz static int ivpu_mmu_cd_add_user(struct ivpu_device *vdev, u32 ssid, dma_addr_t cd_dma) 688*263b2ba5SJacek Lawrynowicz { 689*263b2ba5SJacek Lawrynowicz int ret; 690*263b2ba5SJacek Lawrynowicz 691*263b2ba5SJacek Lawrynowicz if (ssid == 0) { 692*263b2ba5SJacek Lawrynowicz ivpu_err(vdev, "Invalid SSID: %u\n", ssid); 693*263b2ba5SJacek Lawrynowicz return -EINVAL; 694*263b2ba5SJacek Lawrynowicz } 695*263b2ba5SJacek Lawrynowicz 696*263b2ba5SJacek Lawrynowicz ret = ivpu_mmu_cd_add(vdev, ssid, cd_dma); 697*263b2ba5SJacek Lawrynowicz if (ret) 698*263b2ba5SJacek Lawrynowicz ivpu_err(vdev, "Failed to add CD entry SSID=%u: %d\n", ssid, ret); 699*263b2ba5SJacek Lawrynowicz 700*263b2ba5SJacek Lawrynowicz return ret; 701*263b2ba5SJacek Lawrynowicz } 702*263b2ba5SJacek Lawrynowicz 703*263b2ba5SJacek Lawrynowicz int ivpu_mmu_init(struct ivpu_device *vdev) 704*263b2ba5SJacek Lawrynowicz { 705*263b2ba5SJacek Lawrynowicz struct ivpu_mmu_info *mmu = vdev->mmu; 706*263b2ba5SJacek Lawrynowicz int ret; 707*263b2ba5SJacek Lawrynowicz 708*263b2ba5SJacek Lawrynowicz ivpu_dbg(vdev, MMU, "Init..\n"); 709*263b2ba5SJacek Lawrynowicz 710*263b2ba5SJacek Lawrynowicz drmm_mutex_init(&vdev->drm, &mmu->lock); 711*263b2ba5SJacek Lawrynowicz ivpu_mmu_config_check(vdev); 712*263b2ba5SJacek Lawrynowicz 713*263b2ba5SJacek Lawrynowicz ret = ivpu_mmu_structs_alloc(vdev); 714*263b2ba5SJacek Lawrynowicz if (ret) 715*263b2ba5SJacek Lawrynowicz return ret; 716*263b2ba5SJacek Lawrynowicz 717*263b2ba5SJacek Lawrynowicz ret = ivpu_mmu_strtab_init(vdev); 718*263b2ba5SJacek Lawrynowicz if (ret) { 719*263b2ba5SJacek Lawrynowicz ivpu_err(vdev, "Failed to initialize strtab: %d\n", ret); 720*263b2ba5SJacek Lawrynowicz return ret; 721*263b2ba5SJacek Lawrynowicz } 722*263b2ba5SJacek Lawrynowicz 723*263b2ba5SJacek Lawrynowicz ret = ivpu_mmu_cd_add_gbl(vdev); 724*263b2ba5SJacek Lawrynowicz if (ret) { 725*263b2ba5SJacek Lawrynowicz ivpu_err(vdev, "Failed to initialize strtab: %d\n", ret); 726*263b2ba5SJacek Lawrynowicz return ret; 727*263b2ba5SJacek Lawrynowicz } 728*263b2ba5SJacek Lawrynowicz 729*263b2ba5SJacek Lawrynowicz ret = ivpu_mmu_enable(vdev); 730*263b2ba5SJacek Lawrynowicz if (ret) { 731*263b2ba5SJacek Lawrynowicz ivpu_err(vdev, "Failed to resume MMU: %d\n", ret); 732*263b2ba5SJacek Lawrynowicz return ret; 733*263b2ba5SJacek Lawrynowicz } 734*263b2ba5SJacek Lawrynowicz 735*263b2ba5SJacek Lawrynowicz ivpu_dbg(vdev, MMU, "Init done\n"); 736*263b2ba5SJacek Lawrynowicz 737*263b2ba5SJacek Lawrynowicz return 0; 738*263b2ba5SJacek Lawrynowicz } 739*263b2ba5SJacek Lawrynowicz 740*263b2ba5SJacek Lawrynowicz int ivpu_mmu_enable(struct ivpu_device *vdev) 741*263b2ba5SJacek Lawrynowicz { 742*263b2ba5SJacek Lawrynowicz struct ivpu_mmu_info *mmu = vdev->mmu; 743*263b2ba5SJacek Lawrynowicz int ret; 744*263b2ba5SJacek Lawrynowicz 745*263b2ba5SJacek Lawrynowicz mutex_lock(&mmu->lock); 746*263b2ba5SJacek Lawrynowicz 747*263b2ba5SJacek Lawrynowicz mmu->on = true; 748*263b2ba5SJacek Lawrynowicz 749*263b2ba5SJacek Lawrynowicz ret = ivpu_mmu_reset(vdev); 750*263b2ba5SJacek Lawrynowicz if (ret) { 751*263b2ba5SJacek Lawrynowicz ivpu_err(vdev, "Failed to reset MMU: %d\n", ret); 752*263b2ba5SJacek Lawrynowicz goto err; 753*263b2ba5SJacek Lawrynowicz } 754*263b2ba5SJacek Lawrynowicz 755*263b2ba5SJacek Lawrynowicz ret = ivpu_mmu_cmdq_write_cfgi_all(vdev); 756*263b2ba5SJacek Lawrynowicz if (ret) 757*263b2ba5SJacek Lawrynowicz goto err; 758*263b2ba5SJacek Lawrynowicz 759*263b2ba5SJacek Lawrynowicz ret = ivpu_mmu_cmdq_write_tlbi_nsnh_all(vdev); 760*263b2ba5SJacek Lawrynowicz if (ret) 761*263b2ba5SJacek Lawrynowicz goto err; 762*263b2ba5SJacek Lawrynowicz 763*263b2ba5SJacek Lawrynowicz ret = ivpu_mmu_cmdq_sync(vdev); 764*263b2ba5SJacek Lawrynowicz if (ret) 765*263b2ba5SJacek Lawrynowicz goto err; 766*263b2ba5SJacek Lawrynowicz 767*263b2ba5SJacek Lawrynowicz mutex_unlock(&mmu->lock); 768*263b2ba5SJacek Lawrynowicz 769*263b2ba5SJacek Lawrynowicz return 0; 770*263b2ba5SJacek Lawrynowicz err: 771*263b2ba5SJacek Lawrynowicz mmu->on = false; 772*263b2ba5SJacek Lawrynowicz mutex_unlock(&mmu->lock); 773*263b2ba5SJacek Lawrynowicz return ret; 774*263b2ba5SJacek Lawrynowicz } 775*263b2ba5SJacek Lawrynowicz 776*263b2ba5SJacek Lawrynowicz void ivpu_mmu_disable(struct ivpu_device *vdev) 777*263b2ba5SJacek Lawrynowicz { 778*263b2ba5SJacek Lawrynowicz struct ivpu_mmu_info *mmu = vdev->mmu; 779*263b2ba5SJacek Lawrynowicz 780*263b2ba5SJacek Lawrynowicz mutex_lock(&mmu->lock); 781*263b2ba5SJacek Lawrynowicz mmu->on = false; 782*263b2ba5SJacek Lawrynowicz mutex_unlock(&mmu->lock); 783*263b2ba5SJacek Lawrynowicz } 784*263b2ba5SJacek Lawrynowicz 785*263b2ba5SJacek Lawrynowicz static void ivpu_mmu_dump_event(struct ivpu_device *vdev, u32 *event) 786*263b2ba5SJacek Lawrynowicz { 787*263b2ba5SJacek Lawrynowicz u32 ssid = FIELD_GET(IVPU_MMU_EVT_SSID_MASK, event[0]); 788*263b2ba5SJacek Lawrynowicz u32 op = FIELD_GET(IVPU_MMU_EVT_OP_MASK, event[0]); 789*263b2ba5SJacek Lawrynowicz u64 fetch_addr = ((u64)event[7]) << 32 | event[6]; 790*263b2ba5SJacek Lawrynowicz u64 in_addr = ((u64)event[5]) << 32 | event[4]; 791*263b2ba5SJacek Lawrynowicz u32 sid = event[1]; 792*263b2ba5SJacek Lawrynowicz 793*263b2ba5SJacek Lawrynowicz 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", 794*263b2ba5SJacek Lawrynowicz op, ivpu_mmu_event_to_str(op), ssid, sid, event[2], event[3], in_addr, fetch_addr); 795*263b2ba5SJacek Lawrynowicz } 796*263b2ba5SJacek Lawrynowicz 797*263b2ba5SJacek Lawrynowicz static u32 *ivpu_mmu_get_event(struct ivpu_device *vdev) 798*263b2ba5SJacek Lawrynowicz { 799*263b2ba5SJacek Lawrynowicz struct ivpu_mmu_queue *evtq = &vdev->mmu->evtq; 800*263b2ba5SJacek Lawrynowicz u32 idx = IVPU_MMU_Q_IDX(evtq->cons); 801*263b2ba5SJacek Lawrynowicz u32 *evt = evtq->base + (idx * IVPU_MMU_EVTQ_CMD_SIZE); 802*263b2ba5SJacek Lawrynowicz 803*263b2ba5SJacek Lawrynowicz evtq->prod = REGV_RD32(MTL_VPU_HOST_MMU_EVTQ_PROD_SEC); 804*263b2ba5SJacek Lawrynowicz if (!CIRC_CNT(IVPU_MMU_Q_IDX(evtq->prod), IVPU_MMU_Q_IDX(evtq->cons), IVPU_MMU_Q_COUNT)) 805*263b2ba5SJacek Lawrynowicz return NULL; 806*263b2ba5SJacek Lawrynowicz 807*263b2ba5SJacek Lawrynowicz clflush_cache_range(evt, IVPU_MMU_EVTQ_CMD_SIZE); 808*263b2ba5SJacek Lawrynowicz 809*263b2ba5SJacek Lawrynowicz evtq->cons = (evtq->cons + 1) & IVPU_MMU_Q_WRAP_MASK; 810*263b2ba5SJacek Lawrynowicz REGV_WR32(MTL_VPU_HOST_MMU_EVTQ_CONS_SEC, evtq->cons); 811*263b2ba5SJacek Lawrynowicz 812*263b2ba5SJacek Lawrynowicz return evt; 813*263b2ba5SJacek Lawrynowicz } 814*263b2ba5SJacek Lawrynowicz 815*263b2ba5SJacek Lawrynowicz void ivpu_mmu_irq_evtq_handler(struct ivpu_device *vdev) 816*263b2ba5SJacek Lawrynowicz { 817*263b2ba5SJacek Lawrynowicz u32 *event; 818*263b2ba5SJacek Lawrynowicz u32 ssid; 819*263b2ba5SJacek Lawrynowicz 820*263b2ba5SJacek Lawrynowicz ivpu_dbg(vdev, IRQ, "MMU event queue\n"); 821*263b2ba5SJacek Lawrynowicz 822*263b2ba5SJacek Lawrynowicz while ((event = ivpu_mmu_get_event(vdev)) != NULL) { 823*263b2ba5SJacek Lawrynowicz ivpu_mmu_dump_event(vdev, event); 824*263b2ba5SJacek Lawrynowicz 825*263b2ba5SJacek Lawrynowicz ssid = FIELD_GET(IVPU_MMU_EVT_SSID_MASK, event[0]); 826*263b2ba5SJacek Lawrynowicz if (ssid != IVPU_GLOBAL_CONTEXT_MMU_SSID) 827*263b2ba5SJacek Lawrynowicz ivpu_mmu_user_context_mark_invalid(vdev, ssid); 828*263b2ba5SJacek Lawrynowicz } 829*263b2ba5SJacek Lawrynowicz } 830*263b2ba5SJacek Lawrynowicz 831*263b2ba5SJacek Lawrynowicz void ivpu_mmu_irq_gerr_handler(struct ivpu_device *vdev) 832*263b2ba5SJacek Lawrynowicz { 833*263b2ba5SJacek Lawrynowicz u32 gerror_val, gerrorn_val, active; 834*263b2ba5SJacek Lawrynowicz 835*263b2ba5SJacek Lawrynowicz ivpu_dbg(vdev, IRQ, "MMU error\n"); 836*263b2ba5SJacek Lawrynowicz 837*263b2ba5SJacek Lawrynowicz gerror_val = REGV_RD32(MTL_VPU_HOST_MMU_GERROR); 838*263b2ba5SJacek Lawrynowicz gerrorn_val = REGV_RD32(MTL_VPU_HOST_MMU_GERRORN); 839*263b2ba5SJacek Lawrynowicz 840*263b2ba5SJacek Lawrynowicz active = gerror_val ^ gerrorn_val; 841*263b2ba5SJacek Lawrynowicz if (!(active & IVPU_MMU_GERROR_ERR_MASK)) 842*263b2ba5SJacek Lawrynowicz return; 843*263b2ba5SJacek Lawrynowicz 844*263b2ba5SJacek Lawrynowicz if (REG_TEST_FLD(MTL_VPU_HOST_MMU_GERROR, MSI_ABT, active)) 845*263b2ba5SJacek Lawrynowicz ivpu_warn_ratelimited(vdev, "MMU MSI ABT write aborted\n"); 846*263b2ba5SJacek Lawrynowicz 847*263b2ba5SJacek Lawrynowicz if (REG_TEST_FLD(MTL_VPU_HOST_MMU_GERROR, MSI_PRIQ_ABT, active)) 848*263b2ba5SJacek Lawrynowicz ivpu_warn_ratelimited(vdev, "MMU PRIQ MSI ABT write aborted\n"); 849*263b2ba5SJacek Lawrynowicz 850*263b2ba5SJacek Lawrynowicz if (REG_TEST_FLD(MTL_VPU_HOST_MMU_GERROR, MSI_EVTQ_ABT, active)) 851*263b2ba5SJacek Lawrynowicz ivpu_warn_ratelimited(vdev, "MMU EVTQ MSI ABT write aborted\n"); 852*263b2ba5SJacek Lawrynowicz 853*263b2ba5SJacek Lawrynowicz if (REG_TEST_FLD(MTL_VPU_HOST_MMU_GERROR, MSI_CMDQ_ABT, active)) 854*263b2ba5SJacek Lawrynowicz ivpu_warn_ratelimited(vdev, "MMU CMDQ MSI ABT write aborted\n"); 855*263b2ba5SJacek Lawrynowicz 856*263b2ba5SJacek Lawrynowicz if (REG_TEST_FLD(MTL_VPU_HOST_MMU_GERROR, PRIQ_ABT, active)) 857*263b2ba5SJacek Lawrynowicz ivpu_err_ratelimited(vdev, "MMU PRIQ write aborted\n"); 858*263b2ba5SJacek Lawrynowicz 859*263b2ba5SJacek Lawrynowicz if (REG_TEST_FLD(MTL_VPU_HOST_MMU_GERROR, EVTQ_ABT, active)) 860*263b2ba5SJacek Lawrynowicz ivpu_err_ratelimited(vdev, "MMU EVTQ write aborted\n"); 861*263b2ba5SJacek Lawrynowicz 862*263b2ba5SJacek Lawrynowicz if (REG_TEST_FLD(MTL_VPU_HOST_MMU_GERROR, CMDQ, active)) 863*263b2ba5SJacek Lawrynowicz ivpu_err_ratelimited(vdev, "MMU CMDQ write aborted\n"); 864*263b2ba5SJacek Lawrynowicz 865*263b2ba5SJacek Lawrynowicz REGV_WR32(MTL_VPU_HOST_MMU_GERRORN, gerror_val); 866*263b2ba5SJacek Lawrynowicz } 867*263b2ba5SJacek Lawrynowicz 868*263b2ba5SJacek Lawrynowicz int ivpu_mmu_set_pgtable(struct ivpu_device *vdev, int ssid, struct ivpu_mmu_pgtable *pgtable) 869*263b2ba5SJacek Lawrynowicz { 870*263b2ba5SJacek Lawrynowicz return ivpu_mmu_cd_add_user(vdev, ssid, pgtable->pgd_dma); 871*263b2ba5SJacek Lawrynowicz } 872*263b2ba5SJacek Lawrynowicz 873*263b2ba5SJacek Lawrynowicz void ivpu_mmu_clear_pgtable(struct ivpu_device *vdev, int ssid) 874*263b2ba5SJacek Lawrynowicz { 875*263b2ba5SJacek Lawrynowicz ivpu_mmu_cd_add_user(vdev, ssid, 0); /* 0 will clear CD entry */ 876*263b2ba5SJacek Lawrynowicz } 877