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