19436ac31SYang Wang /*
29436ac31SYang Wang  * Copyright 2022 Advanced Micro Devices, Inc.
39436ac31SYang Wang  *
49436ac31SYang Wang  * Permission is hereby granted, free of charge, to any person obtaining a
59436ac31SYang Wang  * copy of this software and associated documentation files (the "Software"),
69436ac31SYang Wang  * to deal in the Software without restriction, including without limitation
79436ac31SYang Wang  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
89436ac31SYang Wang  * and/or sell copies of the Software, and to permit persons to whom the
99436ac31SYang Wang  * Software is furnished to do so, subject to the following conditions:
109436ac31SYang Wang  *
119436ac31SYang Wang  * The above copyright notice and this permission notice shall be included in
129436ac31SYang Wang  * all copies or substantial portions of the Software.
139436ac31SYang Wang  *
149436ac31SYang Wang  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
159436ac31SYang Wang  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
169436ac31SYang Wang  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
179436ac31SYang Wang  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
189436ac31SYang Wang  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
199436ac31SYang Wang  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
209436ac31SYang Wang  * OTHER DEALINGS IN THE SOFTWARE.
219436ac31SYang Wang  *
229436ac31SYang Wang  */
239436ac31SYang Wang 
249436ac31SYang Wang #include "amdgpu.h"
259436ac31SYang Wang #include "gfxhub_v3_0_3.h"
269436ac31SYang Wang 
279436ac31SYang Wang #include "gc/gc_11_0_3_offset.h"
289436ac31SYang Wang #include "gc/gc_11_0_3_sh_mask.h"
299436ac31SYang Wang #include "navi10_enum.h"
309436ac31SYang Wang #include "soc15_common.h"
319436ac31SYang Wang 
329436ac31SYang Wang #define regGCVM_L2_CNTL3_DEFAULT		0x80100007
339436ac31SYang Wang #define regGCVM_L2_CNTL4_DEFAULT		0x000000c1
349436ac31SYang Wang #define regGCVM_L2_CNTL5_DEFAULT		0x00003fe0
359436ac31SYang Wang 
36*fe018cf2SSrinivasan Shanmugam static const char * const gfxhub_client_ids[] = {
379436ac31SYang Wang 	"CB/DB",
389436ac31SYang Wang 	"Reserved",
399436ac31SYang Wang 	"GE1",
409436ac31SYang Wang 	"GE2",
419436ac31SYang Wang 	"CPF",
429436ac31SYang Wang 	"CPC",
439436ac31SYang Wang 	"CPG",
449436ac31SYang Wang 	"RLC",
459436ac31SYang Wang 	"TCP",
469436ac31SYang Wang 	"SQC (inst)",
479436ac31SYang Wang 	"SQC (data)",
489436ac31SYang Wang 	"SQG",
499436ac31SYang Wang 	"Reserved",
509436ac31SYang Wang 	"SDMA0",
519436ac31SYang Wang 	"SDMA1",
529436ac31SYang Wang 	"GCR",
539436ac31SYang Wang 	"SDMA2",
549436ac31SYang Wang 	"SDMA3",
559436ac31SYang Wang };
569436ac31SYang Wang 
gfxhub_v3_0_3_get_invalidate_req(unsigned int vmid,uint32_t flush_type)579436ac31SYang Wang static uint32_t gfxhub_v3_0_3_get_invalidate_req(unsigned int vmid,
589436ac31SYang Wang 					       uint32_t flush_type)
599436ac31SYang Wang {
609436ac31SYang Wang 	u32 req = 0;
619436ac31SYang Wang 
629436ac31SYang Wang 	/* invalidate using legacy mode on vmid*/
639436ac31SYang Wang 	req = REG_SET_FIELD(req, GCVM_INVALIDATE_ENG0_REQ,
649436ac31SYang Wang 			    PER_VMID_INVALIDATE_REQ, 1 << vmid);
659436ac31SYang Wang 	req = REG_SET_FIELD(req, GCVM_INVALIDATE_ENG0_REQ, FLUSH_TYPE, flush_type);
669436ac31SYang Wang 	req = REG_SET_FIELD(req, GCVM_INVALIDATE_ENG0_REQ, INVALIDATE_L2_PTES, 1);
679436ac31SYang Wang 	req = REG_SET_FIELD(req, GCVM_INVALIDATE_ENG0_REQ, INVALIDATE_L2_PDE0, 1);
689436ac31SYang Wang 	req = REG_SET_FIELD(req, GCVM_INVALIDATE_ENG0_REQ, INVALIDATE_L2_PDE1, 1);
699436ac31SYang Wang 	req = REG_SET_FIELD(req, GCVM_INVALIDATE_ENG0_REQ, INVALIDATE_L2_PDE2, 1);
709436ac31SYang Wang 	req = REG_SET_FIELD(req, GCVM_INVALIDATE_ENG0_REQ, INVALIDATE_L1_PTES, 1);
719436ac31SYang Wang 	req = REG_SET_FIELD(req, GCVM_INVALIDATE_ENG0_REQ,
729436ac31SYang Wang 			    CLEAR_PROTECTION_FAULT_STATUS_ADDR,	0);
739436ac31SYang Wang 
749436ac31SYang Wang 	return req;
759436ac31SYang Wang }
769436ac31SYang Wang 
779436ac31SYang Wang static void
gfxhub_v3_0_3_print_l2_protection_fault_status(struct amdgpu_device * adev,uint32_t status)789436ac31SYang Wang gfxhub_v3_0_3_print_l2_protection_fault_status(struct amdgpu_device *adev,
799436ac31SYang Wang 					     uint32_t status)
809436ac31SYang Wang {
819436ac31SYang Wang 	u32 cid = REG_GET_FIELD(status,
829436ac31SYang Wang 				GCVM_L2_PROTECTION_FAULT_STATUS, CID);
839436ac31SYang Wang 
849436ac31SYang Wang 	dev_err(adev->dev,
859436ac31SYang Wang 		"GCVM_L2_PROTECTION_FAULT_STATUS:0x%08X\n",
869436ac31SYang Wang 		status);
879436ac31SYang Wang 	dev_err(adev->dev, "\t Faulty UTCL2 client ID: %s (0x%x)\n",
889436ac31SYang Wang 		cid >= ARRAY_SIZE(gfxhub_client_ids) ? "unknown" : gfxhub_client_ids[cid],
899436ac31SYang Wang 		cid);
909436ac31SYang Wang 	dev_err(adev->dev, "\t MORE_FAULTS: 0x%lx\n",
919436ac31SYang Wang 		REG_GET_FIELD(status,
929436ac31SYang Wang 		GCVM_L2_PROTECTION_FAULT_STATUS, MORE_FAULTS));
939436ac31SYang Wang 	dev_err(adev->dev, "\t WALKER_ERROR: 0x%lx\n",
949436ac31SYang Wang 		REG_GET_FIELD(status,
959436ac31SYang Wang 		GCVM_L2_PROTECTION_FAULT_STATUS, WALKER_ERROR));
969436ac31SYang Wang 	dev_err(adev->dev, "\t PERMISSION_FAULTS: 0x%lx\n",
979436ac31SYang Wang 		REG_GET_FIELD(status,
989436ac31SYang Wang 		GCVM_L2_PROTECTION_FAULT_STATUS, PERMISSION_FAULTS));
999436ac31SYang Wang 	dev_err(adev->dev, "\t MAPPING_ERROR: 0x%lx\n",
1009436ac31SYang Wang 		REG_GET_FIELD(status,
1019436ac31SYang Wang 		GCVM_L2_PROTECTION_FAULT_STATUS, MAPPING_ERROR));
1029436ac31SYang Wang 	dev_err(adev->dev, "\t RW: 0x%lx\n",
1039436ac31SYang Wang 		REG_GET_FIELD(status,
1049436ac31SYang Wang 		GCVM_L2_PROTECTION_FAULT_STATUS, RW));
1059436ac31SYang Wang }
1069436ac31SYang Wang 
gfxhub_v3_0_3_get_fb_location(struct amdgpu_device * adev)1079436ac31SYang Wang static u64 gfxhub_v3_0_3_get_fb_location(struct amdgpu_device *adev)
1089436ac31SYang Wang {
1099436ac31SYang Wang 	u64 base = RREG32_SOC15(GC, 0, regGCMC_VM_FB_LOCATION_BASE);
1109436ac31SYang Wang 
1119436ac31SYang Wang 	base &= GCMC_VM_FB_LOCATION_BASE__FB_BASE_MASK;
1129436ac31SYang Wang 	base <<= 24;
1139436ac31SYang Wang 
1149436ac31SYang Wang 	return base;
1159436ac31SYang Wang }
1169436ac31SYang Wang 
gfxhub_v3_0_3_get_mc_fb_offset(struct amdgpu_device * adev)1179436ac31SYang Wang static u64 gfxhub_v3_0_3_get_mc_fb_offset(struct amdgpu_device *adev)
1189436ac31SYang Wang {
1199436ac31SYang Wang 	return (u64)RREG32_SOC15(GC, 0, regGCMC_VM_FB_OFFSET) << 24;
1209436ac31SYang Wang }
1219436ac31SYang Wang 
gfxhub_v3_0_3_setup_vm_pt_regs(struct amdgpu_device * adev,uint32_t vmid,uint64_t page_table_base)1229436ac31SYang Wang static void gfxhub_v3_0_3_setup_vm_pt_regs(struct amdgpu_device *adev, uint32_t vmid,
1239436ac31SYang Wang 				uint64_t page_table_base)
1249436ac31SYang Wang {
125f4caf584SHawking Zhang 	struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB(0)];
1269436ac31SYang Wang 
1279436ac31SYang Wang 	WREG32_SOC15_OFFSET(GC, 0, regGCVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32,
1289436ac31SYang Wang 			    hub->ctx_addr_distance * vmid,
1299436ac31SYang Wang 			    lower_32_bits(page_table_base));
1309436ac31SYang Wang 
1319436ac31SYang Wang 	WREG32_SOC15_OFFSET(GC, 0, regGCVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32,
1329436ac31SYang Wang 			    hub->ctx_addr_distance * vmid,
1339436ac31SYang Wang 			    upper_32_bits(page_table_base));
1349436ac31SYang Wang }
1359436ac31SYang Wang 
gfxhub_v3_0_3_init_gart_aperture_regs(struct amdgpu_device * adev)1369436ac31SYang Wang static void gfxhub_v3_0_3_init_gart_aperture_regs(struct amdgpu_device *adev)
1379436ac31SYang Wang {
1389436ac31SYang Wang 	uint64_t pt_base = amdgpu_gmc_pd_addr(adev->gart.bo);
1399436ac31SYang Wang 
1409436ac31SYang Wang 	gfxhub_v3_0_3_setup_vm_pt_regs(adev, 0, pt_base);
1419436ac31SYang Wang 
1429436ac31SYang Wang 	WREG32_SOC15(GC, 0, regGCVM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32,
1439436ac31SYang Wang 		     (u32)(adev->gmc.gart_start >> 12));
1449436ac31SYang Wang 	WREG32_SOC15(GC, 0, regGCVM_CONTEXT0_PAGE_TABLE_START_ADDR_HI32,
1459436ac31SYang Wang 		     (u32)(adev->gmc.gart_start >> 44));
1469436ac31SYang Wang 
1479436ac31SYang Wang 	WREG32_SOC15(GC, 0, regGCVM_CONTEXT0_PAGE_TABLE_END_ADDR_LO32,
1489436ac31SYang Wang 		     (u32)(adev->gmc.gart_end >> 12));
1499436ac31SYang Wang 	WREG32_SOC15(GC, 0, regGCVM_CONTEXT0_PAGE_TABLE_END_ADDR_HI32,
1509436ac31SYang Wang 		     (u32)(adev->gmc.gart_end >> 44));
1519436ac31SYang Wang }
1529436ac31SYang Wang 
gfxhub_v3_0_3_init_system_aperture_regs(struct amdgpu_device * adev)1539436ac31SYang Wang static void gfxhub_v3_0_3_init_system_aperture_regs(struct amdgpu_device *adev)
1549436ac31SYang Wang {
1559436ac31SYang Wang 	uint64_t value;
1569436ac31SYang Wang 
1572c763f37SYifan Zha 	if (amdgpu_sriov_vf(adev))
1582c763f37SYifan Zha 		return;
1592c763f37SYifan Zha 
1609436ac31SYang Wang 	/* Disable AGP. */
1619436ac31SYang Wang 	WREG32_SOC15(GC, 0, regGCMC_VM_AGP_BASE, 0);
16273ac3f22SAlex Deucher 	WREG32_SOC15(GC, 0, regGCMC_VM_AGP_BOT, adev->gmc.agp_start >> 24);
16373ac3f22SAlex Deucher 	WREG32_SOC15(GC, 0, regGCMC_VM_AGP_TOP, adev->gmc.agp_end >> 24);
1649436ac31SYang Wang 
1659436ac31SYang Wang 	/* Program the system aperture low logical page number. */
1669436ac31SYang Wang 	WREG32_SOC15(GC, 0, regGCMC_VM_SYSTEM_APERTURE_LOW_ADDR,
16773ac3f22SAlex Deucher 		     min(adev->gmc.fb_start, adev->gmc.agp_start) >> 18);
1689436ac31SYang Wang 	WREG32_SOC15(GC, 0, regGCMC_VM_SYSTEM_APERTURE_HIGH_ADDR,
16973ac3f22SAlex Deucher 		     max(adev->gmc.fb_end, adev->gmc.agp_end) >> 18);
1709436ac31SYang Wang 
1719436ac31SYang Wang 	/* Set default page address. */
1727ccfd79fSChristian König 	value = adev->mem_scratch.gpu_addr - adev->gmc.vram_start
1739436ac31SYang Wang 		+ adev->vm_manager.vram_base_offset;
1749436ac31SYang Wang 	WREG32_SOC15(GC, 0, regGCMC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB,
1759436ac31SYang Wang 		     (u32)(value >> 12));
1769436ac31SYang Wang 	WREG32_SOC15(GC, 0, regGCMC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB,
1779436ac31SYang Wang 		     (u32)(value >> 44));
1789436ac31SYang Wang 
1799436ac31SYang Wang 	/* Program "protection fault". */
1809436ac31SYang Wang 	WREG32_SOC15(GC, 0, regGCVM_L2_PROTECTION_FAULT_DEFAULT_ADDR_LO32,
1819436ac31SYang Wang 		     (u32)(adev->dummy_page_addr >> 12));
1829436ac31SYang Wang 	WREG32_SOC15(GC, 0, regGCVM_L2_PROTECTION_FAULT_DEFAULT_ADDR_HI32,
1839436ac31SYang Wang 		     (u32)((u64)adev->dummy_page_addr >> 44));
1849436ac31SYang Wang 
1859436ac31SYang Wang 	WREG32_FIELD15_PREREG(GC, 0, GCVM_L2_PROTECTION_FAULT_CNTL2,
1869436ac31SYang Wang 		       ACTIVE_PAGE_MIGRATION_PTE_READ_RETRY, 1);
1879436ac31SYang Wang }
1889436ac31SYang Wang 
1899436ac31SYang Wang 
gfxhub_v3_0_3_init_tlb_regs(struct amdgpu_device * adev)1909436ac31SYang Wang static void gfxhub_v3_0_3_init_tlb_regs(struct amdgpu_device *adev)
1919436ac31SYang Wang {
1929436ac31SYang Wang 	uint32_t tmp;
1939436ac31SYang Wang 
1949436ac31SYang Wang 	/* Setup TLB control */
1959436ac31SYang Wang 	tmp = RREG32_SOC15(GC, 0, regGCMC_VM_MX_L1_TLB_CNTL);
1969436ac31SYang Wang 
1979436ac31SYang Wang 	tmp = REG_SET_FIELD(tmp, GCMC_VM_MX_L1_TLB_CNTL, ENABLE_L1_TLB, 1);
1989436ac31SYang Wang 	tmp = REG_SET_FIELD(tmp, GCMC_VM_MX_L1_TLB_CNTL, SYSTEM_ACCESS_MODE, 3);
1999436ac31SYang Wang 	tmp = REG_SET_FIELD(tmp, GCMC_VM_MX_L1_TLB_CNTL,
2009436ac31SYang Wang 			    ENABLE_ADVANCED_DRIVER_MODEL, 1);
2019436ac31SYang Wang 	tmp = REG_SET_FIELD(tmp, GCMC_VM_MX_L1_TLB_CNTL,
2029436ac31SYang Wang 			    SYSTEM_APERTURE_UNMAPPED_ACCESS, 0);
2039436ac31SYang Wang 	tmp = REG_SET_FIELD(tmp, GCMC_VM_MX_L1_TLB_CNTL, ECO_BITS, 0);
2049436ac31SYang Wang 	tmp = REG_SET_FIELD(tmp, GCMC_VM_MX_L1_TLB_CNTL,
2059436ac31SYang Wang 			    MTYPE, MTYPE_UC); /* UC, uncached */
2069436ac31SYang Wang 
2079436ac31SYang Wang 	WREG32_SOC15(GC, 0, regGCMC_VM_MX_L1_TLB_CNTL, tmp);
2089436ac31SYang Wang }
2099436ac31SYang Wang 
gfxhub_v3_0_3_init_cache_regs(struct amdgpu_device * adev)2109436ac31SYang Wang static void gfxhub_v3_0_3_init_cache_regs(struct amdgpu_device *adev)
2119436ac31SYang Wang {
2129436ac31SYang Wang 	uint32_t tmp;
2139436ac31SYang Wang 
2149436ac31SYang Wang 	/* These registers are not accessible to VF-SRIOV.
2159436ac31SYang Wang 	 * The PF will program them instead.
2169436ac31SYang Wang 	 */
2179436ac31SYang Wang 	if (amdgpu_sriov_vf(adev))
2189436ac31SYang Wang 		return;
2199436ac31SYang Wang 
2209436ac31SYang Wang 	/* Setup L2 cache */
2219436ac31SYang Wang 	tmp = RREG32_SOC15(GC, 0, regGCVM_L2_CNTL);
2229436ac31SYang Wang 	tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL, ENABLE_L2_CACHE, 1);
2239436ac31SYang Wang 	tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL, ENABLE_L2_FRAGMENT_PROCESSING, 0);
2249436ac31SYang Wang 	tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL,
2259436ac31SYang Wang 			    ENABLE_DEFAULT_PAGE_OUT_TO_SYSTEM_MEMORY, 1);
2269436ac31SYang Wang 	/* XXX for emulation, Refer to closed source code.*/
2279436ac31SYang Wang 	tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL,
2289436ac31SYang Wang 			    L2_PDE0_CACHE_TAG_GENERATION_MODE, 0);
2299436ac31SYang Wang 	tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL, PDE_FAULT_CLASSIFICATION, 0);
2309436ac31SYang Wang 	tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL, CONTEXT1_IDENTITY_ACCESS_MODE, 1);
2319436ac31SYang Wang 	tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL, IDENTITY_MODE_FRAGMENT_SIZE, 0);
2329436ac31SYang Wang 	WREG32_SOC15(GC, 0, regGCVM_L2_CNTL, tmp);
2339436ac31SYang Wang 
2349436ac31SYang Wang 	tmp = RREG32_SOC15(GC, 0, regGCVM_L2_CNTL2);
2359436ac31SYang Wang 	tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL2, INVALIDATE_ALL_L1_TLBS, 1);
2369436ac31SYang Wang 	tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL2, INVALIDATE_L2_CACHE, 1);
2379436ac31SYang Wang 	WREG32_SOC15(GC, 0, regGCVM_L2_CNTL2, tmp);
2389436ac31SYang Wang 
2399436ac31SYang Wang 	tmp = regGCVM_L2_CNTL3_DEFAULT;
2409436ac31SYang Wang 	if (adev->gmc.translate_further) {
2419436ac31SYang Wang 		tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL3, BANK_SELECT, 12);
2429436ac31SYang Wang 		tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL3,
2439436ac31SYang Wang 				    L2_CACHE_BIGK_FRAGMENT_SIZE, 9);
2449436ac31SYang Wang 	} else {
2459436ac31SYang Wang 		tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL3, BANK_SELECT, 9);
2469436ac31SYang Wang 		tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL3,
2479436ac31SYang Wang 				    L2_CACHE_BIGK_FRAGMENT_SIZE, 6);
2489436ac31SYang Wang 	}
2499436ac31SYang Wang 	WREG32_SOC15(GC, 0, regGCVM_L2_CNTL3, tmp);
2509436ac31SYang Wang 
2519436ac31SYang Wang 	tmp = regGCVM_L2_CNTL4_DEFAULT;
2529436ac31SYang Wang 	tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL4, VMC_TAP_PDE_REQUEST_PHYSICAL, 0);
2539436ac31SYang Wang 	tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL4, VMC_TAP_PTE_REQUEST_PHYSICAL, 0);
2549436ac31SYang Wang 	WREG32_SOC15(GC, 0, regGCVM_L2_CNTL4, tmp);
2559436ac31SYang Wang 
2569436ac31SYang Wang 	tmp = regGCVM_L2_CNTL5_DEFAULT;
2579436ac31SYang Wang 	tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL5, L2_CACHE_SMALLK_FRAGMENT_SIZE, 0);
2589436ac31SYang Wang 	WREG32_SOC15(GC, 0, regGCVM_L2_CNTL5, tmp);
2599436ac31SYang Wang }
2609436ac31SYang Wang 
gfxhub_v3_0_3_enable_system_domain(struct amdgpu_device * adev)2619436ac31SYang Wang static void gfxhub_v3_0_3_enable_system_domain(struct amdgpu_device *adev)
2629436ac31SYang Wang {
2639436ac31SYang Wang 	uint32_t tmp;
2649436ac31SYang Wang 
2659436ac31SYang Wang 	tmp = RREG32_SOC15(GC, 0, regGCVM_CONTEXT0_CNTL);
2669436ac31SYang Wang 	tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT0_CNTL, ENABLE_CONTEXT, 1);
2679436ac31SYang Wang 	tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT0_CNTL, PAGE_TABLE_DEPTH, 0);
2689436ac31SYang Wang 	tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT0_CNTL,
2699436ac31SYang Wang 			    RETRY_PERMISSION_OR_INVALID_PAGE_FAULT, 0);
2709436ac31SYang Wang 	WREG32_SOC15(GC, 0, regGCVM_CONTEXT0_CNTL, tmp);
2719436ac31SYang Wang }
2729436ac31SYang Wang 
gfxhub_v3_0_3_disable_identity_aperture(struct amdgpu_device * adev)2739436ac31SYang Wang static void gfxhub_v3_0_3_disable_identity_aperture(struct amdgpu_device *adev)
2749436ac31SYang Wang {
2759436ac31SYang Wang 	/* These registers are not accessible to VF-SRIOV.
2769436ac31SYang Wang 	 * The PF will program them instead.
2779436ac31SYang Wang 	 */
2789436ac31SYang Wang 	if (amdgpu_sriov_vf(adev))
2799436ac31SYang Wang 		return;
2809436ac31SYang Wang 
2819436ac31SYang Wang 	WREG32_SOC15(GC, 0, regGCVM_L2_CONTEXT1_IDENTITY_APERTURE_LOW_ADDR_LO32,
2829436ac31SYang Wang 		     0xFFFFFFFF);
2839436ac31SYang Wang 	WREG32_SOC15(GC, 0, regGCVM_L2_CONTEXT1_IDENTITY_APERTURE_LOW_ADDR_HI32,
2849436ac31SYang Wang 		     0x0000000F);
2859436ac31SYang Wang 
2869436ac31SYang Wang 	WREG32_SOC15(GC, 0, regGCVM_L2_CONTEXT1_IDENTITY_APERTURE_HIGH_ADDR_LO32,
2879436ac31SYang Wang 		     0);
2889436ac31SYang Wang 	WREG32_SOC15(GC, 0, regGCVM_L2_CONTEXT1_IDENTITY_APERTURE_HIGH_ADDR_HI32,
2899436ac31SYang Wang 		     0);
2909436ac31SYang Wang 
2919436ac31SYang Wang 	WREG32_SOC15(GC, 0, regGCVM_L2_CONTEXT_IDENTITY_PHYSICAL_OFFSET_LO32, 0);
2929436ac31SYang Wang 	WREG32_SOC15(GC, 0, regGCVM_L2_CONTEXT_IDENTITY_PHYSICAL_OFFSET_HI32, 0);
2939436ac31SYang Wang 
2949436ac31SYang Wang }
2959436ac31SYang Wang 
gfxhub_v3_0_3_setup_vmid_config(struct amdgpu_device * adev)2969436ac31SYang Wang static void gfxhub_v3_0_3_setup_vmid_config(struct amdgpu_device *adev)
2979436ac31SYang Wang {
298f4caf584SHawking Zhang 	struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB(0)];
2999436ac31SYang Wang 	int i;
3009436ac31SYang Wang 	uint32_t tmp;
3019436ac31SYang Wang 
3029436ac31SYang Wang 	for (i = 0; i <= 14; i++) {
3039436ac31SYang Wang 		tmp = RREG32_SOC15_OFFSET(GC, 0, regGCVM_CONTEXT1_CNTL, i);
3049436ac31SYang Wang 		tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL, ENABLE_CONTEXT, 1);
3059436ac31SYang Wang 		tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL, PAGE_TABLE_DEPTH,
3069436ac31SYang Wang 				    adev->vm_manager.num_level);
3079436ac31SYang Wang 		tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL,
3089436ac31SYang Wang 				RANGE_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
3099436ac31SYang Wang 		tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL,
3109436ac31SYang Wang 				DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
3119436ac31SYang Wang 		tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL,
3129436ac31SYang Wang 				PDE0_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
3139436ac31SYang Wang 		tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL,
3149436ac31SYang Wang 				VALID_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
3159436ac31SYang Wang 		tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL,
3169436ac31SYang Wang 				READ_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
3179436ac31SYang Wang 		tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL,
3189436ac31SYang Wang 				WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
3199436ac31SYang Wang 		tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL,
3209436ac31SYang Wang 				EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
3219436ac31SYang Wang 		tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL,
3229436ac31SYang Wang 				PAGE_TABLE_BLOCK_SIZE,
3239436ac31SYang Wang 				adev->vm_manager.block_size - 9);
3249436ac31SYang Wang 		/* Send no-retry XNACK on fault to suppress VM fault storm. */
3259436ac31SYang Wang 		tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL,
3269436ac31SYang Wang 				    RETRY_PERMISSION_OR_INVALID_PAGE_FAULT,
3279436ac31SYang Wang 				    !amdgpu_noretry);
3289436ac31SYang Wang 		WREG32_SOC15_OFFSET(GC, 0, regGCVM_CONTEXT1_CNTL,
3299436ac31SYang Wang 				    i * hub->ctx_distance, tmp);
3309436ac31SYang Wang 		WREG32_SOC15_OFFSET(GC, 0, regGCVM_CONTEXT1_PAGE_TABLE_START_ADDR_LO32,
3319436ac31SYang Wang 				    i * hub->ctx_addr_distance, 0);
3329436ac31SYang Wang 		WREG32_SOC15_OFFSET(GC, 0, regGCVM_CONTEXT1_PAGE_TABLE_START_ADDR_HI32,
3339436ac31SYang Wang 				    i * hub->ctx_addr_distance, 0);
3349436ac31SYang Wang 		WREG32_SOC15_OFFSET(GC, 0, regGCVM_CONTEXT1_PAGE_TABLE_END_ADDR_LO32,
3359436ac31SYang Wang 				    i * hub->ctx_addr_distance,
3369436ac31SYang Wang 				    lower_32_bits(adev->vm_manager.max_pfn - 1));
3379436ac31SYang Wang 		WREG32_SOC15_OFFSET(GC, 0, regGCVM_CONTEXT1_PAGE_TABLE_END_ADDR_HI32,
3389436ac31SYang Wang 				    i * hub->ctx_addr_distance,
3399436ac31SYang Wang 				    upper_32_bits(adev->vm_manager.max_pfn - 1));
3409436ac31SYang Wang 	}
3419436ac31SYang Wang 
3429436ac31SYang Wang 	hub->vm_cntx_cntl = tmp;
3439436ac31SYang Wang }
3449436ac31SYang Wang 
gfxhub_v3_0_3_program_invalidation(struct amdgpu_device * adev)3459436ac31SYang Wang static void gfxhub_v3_0_3_program_invalidation(struct amdgpu_device *adev)
3469436ac31SYang Wang {
347f4caf584SHawking Zhang 	struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB(0)];
348*fe018cf2SSrinivasan Shanmugam 	unsigned int i;
3499436ac31SYang Wang 
3509436ac31SYang Wang 	for (i = 0 ; i < 18; ++i) {
3519436ac31SYang Wang 		WREG32_SOC15_OFFSET(GC, 0, regGCVM_INVALIDATE_ENG0_ADDR_RANGE_LO32,
3529436ac31SYang Wang 				    i * hub->eng_addr_distance, 0xffffffff);
3539436ac31SYang Wang 		WREG32_SOC15_OFFSET(GC, 0, regGCVM_INVALIDATE_ENG0_ADDR_RANGE_HI32,
3549436ac31SYang Wang 				    i * hub->eng_addr_distance, 0x1f);
3559436ac31SYang Wang 	}
3569436ac31SYang Wang }
3579436ac31SYang Wang 
gfxhub_v3_0_3_gart_enable(struct amdgpu_device * adev)3589436ac31SYang Wang static int gfxhub_v3_0_3_gart_enable(struct amdgpu_device *adev)
3599436ac31SYang Wang {
3609436ac31SYang Wang 	/* GART Enable. */
3619436ac31SYang Wang 	gfxhub_v3_0_3_init_gart_aperture_regs(adev);
3629436ac31SYang Wang 	gfxhub_v3_0_3_init_system_aperture_regs(adev);
3639436ac31SYang Wang 	gfxhub_v3_0_3_init_tlb_regs(adev);
3649436ac31SYang Wang 	gfxhub_v3_0_3_init_cache_regs(adev);
3659436ac31SYang Wang 
3669436ac31SYang Wang 	gfxhub_v3_0_3_enable_system_domain(adev);
3679436ac31SYang Wang 	gfxhub_v3_0_3_disable_identity_aperture(adev);
3689436ac31SYang Wang 	gfxhub_v3_0_3_setup_vmid_config(adev);
3699436ac31SYang Wang 	gfxhub_v3_0_3_program_invalidation(adev);
3709436ac31SYang Wang 
3719436ac31SYang Wang 	return 0;
3729436ac31SYang Wang }
3739436ac31SYang Wang 
gfxhub_v3_0_3_gart_disable(struct amdgpu_device * adev)3749436ac31SYang Wang static void gfxhub_v3_0_3_gart_disable(struct amdgpu_device *adev)
3759436ac31SYang Wang {
376f4caf584SHawking Zhang 	struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB(0)];
3779436ac31SYang Wang 	u32 tmp;
3789436ac31SYang Wang 	u32 i;
3799436ac31SYang Wang 
3809436ac31SYang Wang 	/* Disable all tables */
3819436ac31SYang Wang 	for (i = 0; i < 16; i++)
3829436ac31SYang Wang 		WREG32_SOC15_OFFSET(GC, 0, regGCVM_CONTEXT0_CNTL,
3839436ac31SYang Wang 				    i * hub->ctx_distance, 0);
3849436ac31SYang Wang 
3859436ac31SYang Wang 	/* Setup TLB control */
3869436ac31SYang Wang 	tmp = RREG32_SOC15(GC, 0, regGCMC_VM_MX_L1_TLB_CNTL);
3879436ac31SYang Wang 	tmp = REG_SET_FIELD(tmp, GCMC_VM_MX_L1_TLB_CNTL, ENABLE_L1_TLB, 0);
3889436ac31SYang Wang 	tmp = REG_SET_FIELD(tmp, GCMC_VM_MX_L1_TLB_CNTL,
3899436ac31SYang Wang 			    ENABLE_ADVANCED_DRIVER_MODEL, 0);
3909436ac31SYang Wang 	WREG32_SOC15(GC, 0, regGCMC_VM_MX_L1_TLB_CNTL, tmp);
3919436ac31SYang Wang 
3929436ac31SYang Wang 	/* Setup L2 cache */
3939436ac31SYang Wang 	WREG32_FIELD15_PREREG(GC, 0, GCVM_L2_CNTL, ENABLE_L2_CACHE, 0);
3949436ac31SYang Wang 	WREG32_SOC15(GC, 0, regGCVM_L2_CNTL3, 0);
3959436ac31SYang Wang }
3969436ac31SYang Wang 
3979436ac31SYang Wang /**
3989436ac31SYang Wang  * gfxhub_v3_0_3_set_fault_enable_default - update GART/VM fault handling
3999436ac31SYang Wang  *
4009436ac31SYang Wang  * @adev: amdgpu_device pointer
4019436ac31SYang Wang  * @value: true redirects VM faults to the default page
4029436ac31SYang Wang  */
gfxhub_v3_0_3_set_fault_enable_default(struct amdgpu_device * adev,bool value)4039436ac31SYang Wang static void gfxhub_v3_0_3_set_fault_enable_default(struct amdgpu_device *adev,
4049436ac31SYang Wang 					  bool value)
4059436ac31SYang Wang {
4069436ac31SYang Wang 	u32 tmp;
4079436ac31SYang Wang 
4089436ac31SYang Wang 	/* These registers are not accessible to VF-SRIOV.
4099436ac31SYang Wang 	 * The PF will program them instead.
4109436ac31SYang Wang 	 */
4119436ac31SYang Wang 	if (amdgpu_sriov_vf(adev))
4129436ac31SYang Wang 		return;
4139436ac31SYang Wang 
4149436ac31SYang Wang 	tmp = RREG32_SOC15(GC, 0, regGCVM_L2_PROTECTION_FAULT_CNTL);
4159436ac31SYang Wang 	tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
4169436ac31SYang Wang 			    RANGE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
4179436ac31SYang Wang 	tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
4189436ac31SYang Wang 			    PDE0_PROTECTION_FAULT_ENABLE_DEFAULT, value);
4199436ac31SYang Wang 	tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
4209436ac31SYang Wang 			    PDE1_PROTECTION_FAULT_ENABLE_DEFAULT, value);
4219436ac31SYang Wang 	tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
4229436ac31SYang Wang 			    PDE2_PROTECTION_FAULT_ENABLE_DEFAULT, value);
4239436ac31SYang Wang 	tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
4249436ac31SYang Wang 			    TRANSLATE_FURTHER_PROTECTION_FAULT_ENABLE_DEFAULT,
4259436ac31SYang Wang 			    value);
4269436ac31SYang Wang 	tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
4279436ac31SYang Wang 			    NACK_PROTECTION_FAULT_ENABLE_DEFAULT, value);
4289436ac31SYang Wang 	tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
4299436ac31SYang Wang 			    DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
4309436ac31SYang Wang 	tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
4319436ac31SYang Wang 			    VALID_PROTECTION_FAULT_ENABLE_DEFAULT, value);
4329436ac31SYang Wang 	tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
4339436ac31SYang Wang 			    READ_PROTECTION_FAULT_ENABLE_DEFAULT, value);
4349436ac31SYang Wang 	tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
4359436ac31SYang Wang 			    WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
4369436ac31SYang Wang 	tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
4379436ac31SYang Wang 			    EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
4389436ac31SYang Wang 	if (!value) {
4399436ac31SYang Wang 		tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
4409436ac31SYang Wang 				CRASH_ON_NO_RETRY_FAULT, 1);
4419436ac31SYang Wang 		tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
4429436ac31SYang Wang 				CRASH_ON_RETRY_FAULT, 1);
4439436ac31SYang Wang 	}
4449436ac31SYang Wang 	WREG32_SOC15(GC, 0, regGCVM_L2_PROTECTION_FAULT_CNTL, tmp);
4459436ac31SYang Wang }
4469436ac31SYang Wang 
4479436ac31SYang Wang static const struct amdgpu_vmhub_funcs gfxhub_v3_0_3_vmhub_funcs = {
4489436ac31SYang Wang 	.print_l2_protection_fault_status = gfxhub_v3_0_3_print_l2_protection_fault_status,
4499436ac31SYang Wang 	.get_invalidate_req = gfxhub_v3_0_3_get_invalidate_req,
4509436ac31SYang Wang };
4519436ac31SYang Wang 
gfxhub_v3_0_3_init(struct amdgpu_device * adev)4529436ac31SYang Wang static void gfxhub_v3_0_3_init(struct amdgpu_device *adev)
4539436ac31SYang Wang {
454f4caf584SHawking Zhang 	struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB(0)];
4559436ac31SYang Wang 
4569436ac31SYang Wang 	hub->ctx0_ptb_addr_lo32 =
4579436ac31SYang Wang 		SOC15_REG_OFFSET(GC, 0,
4589436ac31SYang Wang 				 regGCVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32);
4599436ac31SYang Wang 	hub->ctx0_ptb_addr_hi32 =
4609436ac31SYang Wang 		SOC15_REG_OFFSET(GC, 0,
4619436ac31SYang Wang 				 regGCVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32);
4629436ac31SYang Wang 	hub->vm_inv_eng0_sem =
4639436ac31SYang Wang 		SOC15_REG_OFFSET(GC, 0, regGCVM_INVALIDATE_ENG0_SEM);
4649436ac31SYang Wang 	hub->vm_inv_eng0_req =
4659436ac31SYang Wang 		SOC15_REG_OFFSET(GC, 0, regGCVM_INVALIDATE_ENG0_REQ);
4669436ac31SYang Wang 	hub->vm_inv_eng0_ack =
4679436ac31SYang Wang 		SOC15_REG_OFFSET(GC, 0, regGCVM_INVALIDATE_ENG0_ACK);
4689436ac31SYang Wang 	hub->vm_context0_cntl =
4699436ac31SYang Wang 		SOC15_REG_OFFSET(GC, 0, regGCVM_CONTEXT0_CNTL);
4709436ac31SYang Wang 	hub->vm_l2_pro_fault_status =
4719436ac31SYang Wang 		SOC15_REG_OFFSET(GC, 0, regGCVM_L2_PROTECTION_FAULT_STATUS);
4729436ac31SYang Wang 	hub->vm_l2_pro_fault_cntl =
4739436ac31SYang Wang 		SOC15_REG_OFFSET(GC, 0, regGCVM_L2_PROTECTION_FAULT_CNTL);
4749436ac31SYang Wang 
4759436ac31SYang Wang 	hub->ctx_distance = regGCVM_CONTEXT1_CNTL - regGCVM_CONTEXT0_CNTL;
4769436ac31SYang Wang 	hub->ctx_addr_distance = regGCVM_CONTEXT1_PAGE_TABLE_BASE_ADDR_LO32 -
4779436ac31SYang Wang 		regGCVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32;
4789436ac31SYang Wang 	hub->eng_distance = regGCVM_INVALIDATE_ENG1_REQ -
4799436ac31SYang Wang 		regGCVM_INVALIDATE_ENG0_REQ;
4809436ac31SYang Wang 	hub->eng_addr_distance = regGCVM_INVALIDATE_ENG1_ADDR_RANGE_LO32 -
4819436ac31SYang Wang 		regGCVM_INVALIDATE_ENG0_ADDR_RANGE_LO32;
4829436ac31SYang Wang 
4839436ac31SYang Wang 	hub->vm_cntx_cntl_vm_fault = GCVM_CONTEXT1_CNTL__RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK |
4849436ac31SYang Wang 		GCVM_CONTEXT1_CNTL__DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK |
4859436ac31SYang Wang 		GCVM_CONTEXT1_CNTL__PDE0_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK |
4869436ac31SYang Wang 		GCVM_CONTEXT1_CNTL__VALID_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK |
4879436ac31SYang Wang 		GCVM_CONTEXT1_CNTL__READ_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK |
4889436ac31SYang Wang 		GCVM_CONTEXT1_CNTL__WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK |
4899436ac31SYang Wang 		GCVM_CONTEXT1_CNTL__EXECUTE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK;
4909436ac31SYang Wang 
4919436ac31SYang Wang 	hub->vmhub_funcs = &gfxhub_v3_0_3_vmhub_funcs;
4929436ac31SYang Wang }
4939436ac31SYang Wang 
4949436ac31SYang Wang const struct amdgpu_gfxhub_funcs gfxhub_v3_0_3_funcs = {
4959436ac31SYang Wang 	.get_fb_location = gfxhub_v3_0_3_get_fb_location,
4969436ac31SYang Wang 	.get_mc_fb_offset = gfxhub_v3_0_3_get_mc_fb_offset,
4979436ac31SYang Wang 	.setup_vm_pt_regs = gfxhub_v3_0_3_setup_vm_pt_regs,
4989436ac31SYang Wang 	.gart_enable = gfxhub_v3_0_3_gart_enable,
4999436ac31SYang Wang 	.gart_disable = gfxhub_v3_0_3_gart_disable,
5009436ac31SYang Wang 	.set_fault_enable_default = gfxhub_v3_0_3_set_fault_enable_default,
5019436ac31SYang Wang 	.init = gfxhub_v3_0_3_init,
5029436ac31SYang Wang };
503