12279b4e5STianci.Yin /*
22279b4e5STianci.Yin  * Copyright 2021 Advanced Micro Devices, Inc.
32279b4e5STianci.Yin  *
42279b4e5STianci.Yin  * Permission is hereby granted, free of charge, to any person obtaining a
52279b4e5STianci.Yin  * copy of this software and associated documentation files (the "Software"),
62279b4e5STianci.Yin  * to deal in the Software without restriction, including without limitation
72279b4e5STianci.Yin  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
82279b4e5STianci.Yin  * and/or sell copies of the Software, and to permit persons to whom the
92279b4e5STianci.Yin  * Software is furnished to do so, subject to the following conditions:
102279b4e5STianci.Yin  *
112279b4e5STianci.Yin  * The above copyright notice and this permission notice shall be included in
122279b4e5STianci.Yin  * all copies or substantial portions of the Software.
132279b4e5STianci.Yin  *
142279b4e5STianci.Yin  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
152279b4e5STianci.Yin  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
162279b4e5STianci.Yin  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
172279b4e5STianci.Yin  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
182279b4e5STianci.Yin  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
192279b4e5STianci.Yin  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
202279b4e5STianci.Yin  * OTHER DEALINGS IN THE SOFTWARE.
212279b4e5STianci.Yin  *
222279b4e5STianci.Yin  */
232279b4e5STianci.Yin 
242279b4e5STianci.Yin #include "amdgpu.h"
252279b4e5STianci.Yin #include "gfxhub_v3_0.h"
262279b4e5STianci.Yin 
272279b4e5STianci.Yin #include "gc/gc_11_0_0_offset.h"
282279b4e5STianci.Yin #include "gc/gc_11_0_0_sh_mask.h"
292279b4e5STianci.Yin #include "navi10_enum.h"
302279b4e5STianci.Yin #include "soc15_common.h"
312279b4e5STianci.Yin 
322279b4e5STianci.Yin #define regGCVM_L2_CNTL3_DEFAULT		0x80100007
332279b4e5STianci.Yin #define regGCVM_L2_CNTL4_DEFAULT		0x000000c1
342279b4e5STianci.Yin #define regGCVM_L2_CNTL5_DEFAULT		0x00003fe0
352279b4e5STianci.Yin 
362279b4e5STianci.Yin static const char *gfxhub_client_ids[] = {
372279b4e5STianci.Yin 	"CB/DB",
382279b4e5STianci.Yin 	"Reserved",
392279b4e5STianci.Yin 	"GE1",
402279b4e5STianci.Yin 	"GE2",
412279b4e5STianci.Yin 	"CPF",
422279b4e5STianci.Yin 	"CPC",
432279b4e5STianci.Yin 	"CPG",
442279b4e5STianci.Yin 	"RLC",
452279b4e5STianci.Yin 	"TCP",
462279b4e5STianci.Yin 	"SQC (inst)",
472279b4e5STianci.Yin 	"SQC (data)",
482279b4e5STianci.Yin 	"SQG",
492279b4e5STianci.Yin 	"Reserved",
502279b4e5STianci.Yin 	"SDMA0",
512279b4e5STianci.Yin 	"SDMA1",
522279b4e5STianci.Yin 	"GCR",
532279b4e5STianci.Yin 	"SDMA2",
542279b4e5STianci.Yin 	"SDMA3",
552279b4e5STianci.Yin };
562279b4e5STianci.Yin 
572279b4e5STianci.Yin static uint32_t gfxhub_v3_0_get_invalidate_req(unsigned int vmid,
582279b4e5STianci.Yin 					       uint32_t flush_type)
592279b4e5STianci.Yin {
602279b4e5STianci.Yin 	u32 req = 0;
612279b4e5STianci.Yin 
622279b4e5STianci.Yin 	/* invalidate using legacy mode on vmid*/
632279b4e5STianci.Yin 	req = REG_SET_FIELD(req, GCVM_INVALIDATE_ENG0_REQ,
642279b4e5STianci.Yin 			    PER_VMID_INVALIDATE_REQ, 1 << vmid);
652279b4e5STianci.Yin 	req = REG_SET_FIELD(req, GCVM_INVALIDATE_ENG0_REQ, FLUSH_TYPE, flush_type);
662279b4e5STianci.Yin 	req = REG_SET_FIELD(req, GCVM_INVALIDATE_ENG0_REQ, INVALIDATE_L2_PTES, 1);
672279b4e5STianci.Yin 	req = REG_SET_FIELD(req, GCVM_INVALIDATE_ENG0_REQ, INVALIDATE_L2_PDE0, 1);
682279b4e5STianci.Yin 	req = REG_SET_FIELD(req, GCVM_INVALIDATE_ENG0_REQ, INVALIDATE_L2_PDE1, 1);
692279b4e5STianci.Yin 	req = REG_SET_FIELD(req, GCVM_INVALIDATE_ENG0_REQ, INVALIDATE_L2_PDE2, 1);
702279b4e5STianci.Yin 	req = REG_SET_FIELD(req, GCVM_INVALIDATE_ENG0_REQ, INVALIDATE_L1_PTES, 1);
712279b4e5STianci.Yin 	req = REG_SET_FIELD(req, GCVM_INVALIDATE_ENG0_REQ,
722279b4e5STianci.Yin 			    CLEAR_PROTECTION_FAULT_STATUS_ADDR,	0);
732279b4e5STianci.Yin 
742279b4e5STianci.Yin 	return req;
752279b4e5STianci.Yin }
762279b4e5STianci.Yin 
772279b4e5STianci.Yin static void
782279b4e5STianci.Yin gfxhub_v3_0_print_l2_protection_fault_status(struct amdgpu_device *adev,
792279b4e5STianci.Yin 					     uint32_t status)
802279b4e5STianci.Yin {
812279b4e5STianci.Yin 	u32 cid = REG_GET_FIELD(status,
822279b4e5STianci.Yin 				GCVM_L2_PROTECTION_FAULT_STATUS, CID);
832279b4e5STianci.Yin 
842279b4e5STianci.Yin 	dev_err(adev->dev,
852279b4e5STianci.Yin 		"GCVM_L2_PROTECTION_FAULT_STATUS:0x%08X\n",
862279b4e5STianci.Yin 		status);
872279b4e5STianci.Yin 	dev_err(adev->dev, "\t Faulty UTCL2 client ID: %s (0x%x)\n",
882279b4e5STianci.Yin 		cid >= ARRAY_SIZE(gfxhub_client_ids) ? "unknown" : gfxhub_client_ids[cid],
892279b4e5STianci.Yin 		cid);
902279b4e5STianci.Yin 	dev_err(adev->dev, "\t MORE_FAULTS: 0x%lx\n",
912279b4e5STianci.Yin 		REG_GET_FIELD(status,
922279b4e5STianci.Yin 		GCVM_L2_PROTECTION_FAULT_STATUS, MORE_FAULTS));
932279b4e5STianci.Yin 	dev_err(adev->dev, "\t WALKER_ERROR: 0x%lx\n",
942279b4e5STianci.Yin 		REG_GET_FIELD(status,
952279b4e5STianci.Yin 		GCVM_L2_PROTECTION_FAULT_STATUS, WALKER_ERROR));
962279b4e5STianci.Yin 	dev_err(adev->dev, "\t PERMISSION_FAULTS: 0x%lx\n",
972279b4e5STianci.Yin 		REG_GET_FIELD(status,
982279b4e5STianci.Yin 		GCVM_L2_PROTECTION_FAULT_STATUS, PERMISSION_FAULTS));
992279b4e5STianci.Yin 	dev_err(adev->dev, "\t MAPPING_ERROR: 0x%lx\n",
1002279b4e5STianci.Yin 		REG_GET_FIELD(status,
1012279b4e5STianci.Yin 		GCVM_L2_PROTECTION_FAULT_STATUS, MAPPING_ERROR));
1022279b4e5STianci.Yin 	dev_err(adev->dev, "\t RW: 0x%lx\n",
1032279b4e5STianci.Yin 		REG_GET_FIELD(status,
1042279b4e5STianci.Yin 		GCVM_L2_PROTECTION_FAULT_STATUS, RW));
1052279b4e5STianci.Yin }
1062279b4e5STianci.Yin 
1072279b4e5STianci.Yin static u64 gfxhub_v3_0_get_fb_location(struct amdgpu_device *adev)
1082279b4e5STianci.Yin {
1092279b4e5STianci.Yin 	u64 base = RREG32_SOC15(GC, 0, regGCMC_VM_FB_LOCATION_BASE);
1102279b4e5STianci.Yin 
1112279b4e5STianci.Yin 	base &= GCMC_VM_FB_LOCATION_BASE__FB_BASE_MASK;
1122279b4e5STianci.Yin 	base <<= 24;
1132279b4e5STianci.Yin 
1142279b4e5STianci.Yin 	return base;
1152279b4e5STianci.Yin }
1162279b4e5STianci.Yin 
1172279b4e5STianci.Yin static u64 gfxhub_v3_0_get_mc_fb_offset(struct amdgpu_device *adev)
1182279b4e5STianci.Yin {
1192279b4e5STianci.Yin 	return (u64)RREG32_SOC15(GC, 0, regGCMC_VM_FB_OFFSET) << 24;
1202279b4e5STianci.Yin }
1212279b4e5STianci.Yin 
1222279b4e5STianci.Yin static void gfxhub_v3_0_setup_vm_pt_regs(struct amdgpu_device *adev, uint32_t vmid,
1232279b4e5STianci.Yin 				uint64_t page_table_base)
1242279b4e5STianci.Yin {
1252279b4e5STianci.Yin 	struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB_0];
1262279b4e5STianci.Yin 
1272279b4e5STianci.Yin 	WREG32_SOC15_OFFSET(GC, 0, regGCVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32,
1282279b4e5STianci.Yin 			    hub->ctx_addr_distance * vmid,
1292279b4e5STianci.Yin 			    lower_32_bits(page_table_base));
1302279b4e5STianci.Yin 
1312279b4e5STianci.Yin 	WREG32_SOC15_OFFSET(GC, 0, regGCVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32,
1322279b4e5STianci.Yin 			    hub->ctx_addr_distance * vmid,
1332279b4e5STianci.Yin 			    upper_32_bits(page_table_base));
1342279b4e5STianci.Yin }
1352279b4e5STianci.Yin 
1362279b4e5STianci.Yin static void gfxhub_v3_0_init_gart_aperture_regs(struct amdgpu_device *adev)
1372279b4e5STianci.Yin {
1382279b4e5STianci.Yin 	uint64_t pt_base = amdgpu_gmc_pd_addr(adev->gart.bo);
1392279b4e5STianci.Yin 
1402279b4e5STianci.Yin 	gfxhub_v3_0_setup_vm_pt_regs(adev, 0, pt_base);
1412279b4e5STianci.Yin 
1422279b4e5STianci.Yin 	WREG32_SOC15(GC, 0, regGCVM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32,
1432279b4e5STianci.Yin 		     (u32)(adev->gmc.gart_start >> 12));
1442279b4e5STianci.Yin 	WREG32_SOC15(GC, 0, regGCVM_CONTEXT0_PAGE_TABLE_START_ADDR_HI32,
1452279b4e5STianci.Yin 		     (u32)(adev->gmc.gart_start >> 44));
1462279b4e5STianci.Yin 
1472279b4e5STianci.Yin 	WREG32_SOC15(GC, 0, regGCVM_CONTEXT0_PAGE_TABLE_END_ADDR_LO32,
1482279b4e5STianci.Yin 		     (u32)(adev->gmc.gart_end >> 12));
1492279b4e5STianci.Yin 	WREG32_SOC15(GC, 0, regGCVM_CONTEXT0_PAGE_TABLE_END_ADDR_HI32,
1502279b4e5STianci.Yin 		     (u32)(adev->gmc.gart_end >> 44));
1512279b4e5STianci.Yin }
1522279b4e5STianci.Yin 
1532279b4e5STianci.Yin static void gfxhub_v3_0_init_system_aperture_regs(struct amdgpu_device *adev)
1542279b4e5STianci.Yin {
1552279b4e5STianci.Yin 	uint64_t value;
1562279b4e5STianci.Yin 
1572279b4e5STianci.Yin 	/* Disable AGP. */
1582279b4e5STianci.Yin 	WREG32_SOC15(GC, 0, regGCMC_VM_AGP_BASE, 0);
1592279b4e5STianci.Yin 	WREG32_SOC15(GC, 0, regGCMC_VM_AGP_TOP, 0);
1602279b4e5STianci.Yin 	WREG32_SOC15(GC, 0, regGCMC_VM_AGP_BOT, 0x00FFFFFF);
1612279b4e5STianci.Yin 
1622279b4e5STianci.Yin 	/* Program the system aperture low logical page number. */
1632279b4e5STianci.Yin 	WREG32_SOC15(GC, 0, regGCMC_VM_SYSTEM_APERTURE_LOW_ADDR,
1642279b4e5STianci.Yin 		     adev->gmc.vram_start >> 18);
1652279b4e5STianci.Yin 	WREG32_SOC15(GC, 0, regGCMC_VM_SYSTEM_APERTURE_HIGH_ADDR,
1662279b4e5STianci.Yin 		     adev->gmc.vram_end >> 18);
1672279b4e5STianci.Yin 
1682279b4e5STianci.Yin 	/* Set default page address. */
1692279b4e5STianci.Yin 	value = adev->vram_scratch.gpu_addr - adev->gmc.vram_start
1702279b4e5STianci.Yin 		+ adev->vm_manager.vram_base_offset;
1712279b4e5STianci.Yin 	WREG32_SOC15(GC, 0, regGCMC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB,
1722279b4e5STianci.Yin 		     (u32)(value >> 12));
1732279b4e5STianci.Yin 	WREG32_SOC15(GC, 0, regGCMC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB,
1742279b4e5STianci.Yin 		     (u32)(value >> 44));
1752279b4e5STianci.Yin 
1762279b4e5STianci.Yin 	/* Program "protection fault". */
1772279b4e5STianci.Yin 	WREG32_SOC15(GC, 0, regGCVM_L2_PROTECTION_FAULT_DEFAULT_ADDR_LO32,
1782279b4e5STianci.Yin 		     (u32)(adev->dummy_page_addr >> 12));
1792279b4e5STianci.Yin 	WREG32_SOC15(GC, 0, regGCVM_L2_PROTECTION_FAULT_DEFAULT_ADDR_HI32,
1802279b4e5STianci.Yin 		     (u32)((u64)adev->dummy_page_addr >> 44));
1812279b4e5STianci.Yin 
1822279b4e5STianci.Yin 	WREG32_FIELD15_PREREG(GC, 0, GCVM_L2_PROTECTION_FAULT_CNTL2,
1832279b4e5STianci.Yin 		       ACTIVE_PAGE_MIGRATION_PTE_READ_RETRY, 1);
1842279b4e5STianci.Yin }
1852279b4e5STianci.Yin 
1862279b4e5STianci.Yin 
1872279b4e5STianci.Yin static void gfxhub_v3_0_init_tlb_regs(struct amdgpu_device *adev)
1882279b4e5STianci.Yin {
1892279b4e5STianci.Yin 	uint32_t tmp;
1902279b4e5STianci.Yin 
1912279b4e5STianci.Yin 	/* Setup TLB control */
1922279b4e5STianci.Yin 	tmp = RREG32_SOC15(GC, 0, regGCMC_VM_MX_L1_TLB_CNTL);
1932279b4e5STianci.Yin 
1942279b4e5STianci.Yin 	tmp = REG_SET_FIELD(tmp, GCMC_VM_MX_L1_TLB_CNTL, ENABLE_L1_TLB, 1);
1952279b4e5STianci.Yin 	tmp = REG_SET_FIELD(tmp, GCMC_VM_MX_L1_TLB_CNTL, SYSTEM_ACCESS_MODE, 3);
1962279b4e5STianci.Yin 	tmp = REG_SET_FIELD(tmp, GCMC_VM_MX_L1_TLB_CNTL,
1972279b4e5STianci.Yin 			    ENABLE_ADVANCED_DRIVER_MODEL, 1);
1982279b4e5STianci.Yin 	tmp = REG_SET_FIELD(tmp, GCMC_VM_MX_L1_TLB_CNTL,
1992279b4e5STianci.Yin 			    SYSTEM_APERTURE_UNMAPPED_ACCESS, 0);
2002279b4e5STianci.Yin 	tmp = REG_SET_FIELD(tmp, GCMC_VM_MX_L1_TLB_CNTL, ECO_BITS, 0);
2012279b4e5STianci.Yin 	tmp = REG_SET_FIELD(tmp, GCMC_VM_MX_L1_TLB_CNTL,
2022279b4e5STianci.Yin 			    MTYPE, MTYPE_UC); /* UC, uncached */
2032279b4e5STianci.Yin 
2042279b4e5STianci.Yin 	WREG32_SOC15(GC, 0, regGCMC_VM_MX_L1_TLB_CNTL, tmp);
2052279b4e5STianci.Yin }
2062279b4e5STianci.Yin 
2072279b4e5STianci.Yin static void gfxhub_v3_0_init_cache_regs(struct amdgpu_device *adev)
2082279b4e5STianci.Yin {
2092279b4e5STianci.Yin 	uint32_t tmp;
2102279b4e5STianci.Yin 
2112279b4e5STianci.Yin 	/* These registers are not accessible to VF-SRIOV.
2122279b4e5STianci.Yin 	 * The PF will program them instead.
2132279b4e5STianci.Yin 	 */
2142279b4e5STianci.Yin 	if (amdgpu_sriov_vf(adev))
2152279b4e5STianci.Yin 		return;
2162279b4e5STianci.Yin 
2172279b4e5STianci.Yin 	/* Setup L2 cache */
2182279b4e5STianci.Yin 	tmp = RREG32_SOC15(GC, 0, regGCVM_L2_CNTL);
2192279b4e5STianci.Yin 	tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL, ENABLE_L2_CACHE, 1);
2202279b4e5STianci.Yin 	tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL, ENABLE_L2_FRAGMENT_PROCESSING, 0);
2212279b4e5STianci.Yin 	tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL,
2222279b4e5STianci.Yin 			    ENABLE_DEFAULT_PAGE_OUT_TO_SYSTEM_MEMORY, 1);
2232279b4e5STianci.Yin 	/* XXX for emulation, Refer to closed source code.*/
2242279b4e5STianci.Yin 	tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL,
2252279b4e5STianci.Yin 			    L2_PDE0_CACHE_TAG_GENERATION_MODE, 0);
2262279b4e5STianci.Yin 	tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL, PDE_FAULT_CLASSIFICATION, 0);
2272279b4e5STianci.Yin 	tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL, CONTEXT1_IDENTITY_ACCESS_MODE, 1);
2282279b4e5STianci.Yin 	tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL, IDENTITY_MODE_FRAGMENT_SIZE, 0);
2292279b4e5STianci.Yin 	WREG32_SOC15(GC, 0, regGCVM_L2_CNTL, tmp);
2302279b4e5STianci.Yin 
2312279b4e5STianci.Yin 	tmp = RREG32_SOC15(GC, 0, regGCVM_L2_CNTL2);
2322279b4e5STianci.Yin 	tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL2, INVALIDATE_ALL_L1_TLBS, 1);
2332279b4e5STianci.Yin 	tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL2, INVALIDATE_L2_CACHE, 1);
2342279b4e5STianci.Yin 	WREG32_SOC15(GC, 0, regGCVM_L2_CNTL2, tmp);
2352279b4e5STianci.Yin 
2362279b4e5STianci.Yin 	tmp = regGCVM_L2_CNTL3_DEFAULT;
2372279b4e5STianci.Yin 	if (adev->gmc.translate_further) {
2382279b4e5STianci.Yin 		tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL3, BANK_SELECT, 12);
2392279b4e5STianci.Yin 		tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL3,
2402279b4e5STianci.Yin 				    L2_CACHE_BIGK_FRAGMENT_SIZE, 9);
2412279b4e5STianci.Yin 	} else {
2422279b4e5STianci.Yin 		tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL3, BANK_SELECT, 9);
2432279b4e5STianci.Yin 		tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL3,
2442279b4e5STianci.Yin 				    L2_CACHE_BIGK_FRAGMENT_SIZE, 6);
2452279b4e5STianci.Yin 	}
2462279b4e5STianci.Yin 	WREG32_SOC15(GC, 0, regGCVM_L2_CNTL3, tmp);
2472279b4e5STianci.Yin 
2482279b4e5STianci.Yin 	tmp = regGCVM_L2_CNTL4_DEFAULT;
2492279b4e5STianci.Yin 	tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL4, VMC_TAP_PDE_REQUEST_PHYSICAL, 0);
2502279b4e5STianci.Yin 	tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL4, VMC_TAP_PTE_REQUEST_PHYSICAL, 0);
2512279b4e5STianci.Yin 	WREG32_SOC15(GC, 0, regGCVM_L2_CNTL4, tmp);
2522279b4e5STianci.Yin 
2532279b4e5STianci.Yin 	tmp = regGCVM_L2_CNTL5_DEFAULT;
2542279b4e5STianci.Yin 	tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL5, L2_CACHE_SMALLK_FRAGMENT_SIZE, 0);
2552279b4e5STianci.Yin 	WREG32_SOC15(GC, 0, regGCVM_L2_CNTL5, tmp);
2562279b4e5STianci.Yin }
2572279b4e5STianci.Yin 
2582279b4e5STianci.Yin static void gfxhub_v3_0_enable_system_domain(struct amdgpu_device *adev)
2592279b4e5STianci.Yin {
2602279b4e5STianci.Yin 	uint32_t tmp;
2612279b4e5STianci.Yin 
2622279b4e5STianci.Yin 	tmp = RREG32_SOC15(GC, 0, regGCVM_CONTEXT0_CNTL);
2632279b4e5STianci.Yin 	tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT0_CNTL, ENABLE_CONTEXT, 1);
2642279b4e5STianci.Yin 	tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT0_CNTL, PAGE_TABLE_DEPTH, 0);
2652279b4e5STianci.Yin 	tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT0_CNTL,
2662279b4e5STianci.Yin 			    RETRY_PERMISSION_OR_INVALID_PAGE_FAULT, 0);
2672279b4e5STianci.Yin 	WREG32_SOC15(GC, 0, regGCVM_CONTEXT0_CNTL, tmp);
2682279b4e5STianci.Yin }
2692279b4e5STianci.Yin 
2702279b4e5STianci.Yin static void gfxhub_v3_0_disable_identity_aperture(struct amdgpu_device *adev)
2712279b4e5STianci.Yin {
2722279b4e5STianci.Yin 	/* These registers are not accessible to VF-SRIOV.
2732279b4e5STianci.Yin 	 * The PF will program them instead.
2742279b4e5STianci.Yin 	 */
2752279b4e5STianci.Yin 	if (amdgpu_sriov_vf(adev))
2762279b4e5STianci.Yin 		return;
2772279b4e5STianci.Yin 
2782279b4e5STianci.Yin 	WREG32_SOC15(GC, 0, regGCVM_L2_CONTEXT1_IDENTITY_APERTURE_LOW_ADDR_LO32,
2792279b4e5STianci.Yin 		     0xFFFFFFFF);
2802279b4e5STianci.Yin 	WREG32_SOC15(GC, 0, regGCVM_L2_CONTEXT1_IDENTITY_APERTURE_LOW_ADDR_HI32,
2812279b4e5STianci.Yin 		     0x0000000F);
2822279b4e5STianci.Yin 
2832279b4e5STianci.Yin 	WREG32_SOC15(GC, 0, regGCVM_L2_CONTEXT1_IDENTITY_APERTURE_HIGH_ADDR_LO32,
2842279b4e5STianci.Yin 		     0);
2852279b4e5STianci.Yin 	WREG32_SOC15(GC, 0, regGCVM_L2_CONTEXT1_IDENTITY_APERTURE_HIGH_ADDR_HI32,
2862279b4e5STianci.Yin 		     0);
2872279b4e5STianci.Yin 
2882279b4e5STianci.Yin 	WREG32_SOC15(GC, 0, regGCVM_L2_CONTEXT_IDENTITY_PHYSICAL_OFFSET_LO32, 0);
2892279b4e5STianci.Yin 	WREG32_SOC15(GC, 0, regGCVM_L2_CONTEXT_IDENTITY_PHYSICAL_OFFSET_HI32, 0);
2902279b4e5STianci.Yin 
2912279b4e5STianci.Yin }
2922279b4e5STianci.Yin 
2932279b4e5STianci.Yin static void gfxhub_v3_0_setup_vmid_config(struct amdgpu_device *adev)
2942279b4e5STianci.Yin {
2952279b4e5STianci.Yin 	struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB_0];
2962279b4e5STianci.Yin 	int i;
2972279b4e5STianci.Yin 	uint32_t tmp;
2982279b4e5STianci.Yin 
2992279b4e5STianci.Yin 	for (i = 0; i <= 14; i++) {
3002279b4e5STianci.Yin 		tmp = RREG32_SOC15_OFFSET(GC, 0, regGCVM_CONTEXT1_CNTL, i);
3012279b4e5STianci.Yin 		tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL, ENABLE_CONTEXT, 1);
3022279b4e5STianci.Yin 		tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL, PAGE_TABLE_DEPTH,
3032279b4e5STianci.Yin 				    adev->vm_manager.num_level);
3042279b4e5STianci.Yin 		tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL,
3052279b4e5STianci.Yin 				RANGE_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
3062279b4e5STianci.Yin 		tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL,
3072279b4e5STianci.Yin 				DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
3082279b4e5STianci.Yin 		tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL,
3092279b4e5STianci.Yin 				PDE0_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
3102279b4e5STianci.Yin 		tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL,
3112279b4e5STianci.Yin 				VALID_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
3122279b4e5STianci.Yin 		tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL,
3132279b4e5STianci.Yin 				READ_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
3142279b4e5STianci.Yin 		tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL,
3152279b4e5STianci.Yin 				WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
3162279b4e5STianci.Yin 		tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL,
3172279b4e5STianci.Yin 				EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
3182279b4e5STianci.Yin 		tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL,
3192279b4e5STianci.Yin 				PAGE_TABLE_BLOCK_SIZE,
3202279b4e5STianci.Yin 				adev->vm_manager.block_size - 9);
3212279b4e5STianci.Yin 		/* Send no-retry XNACK on fault to suppress VM fault storm. */
3222279b4e5STianci.Yin 		tmp = REG_SET_FIELD(tmp, GCVM_CONTEXT1_CNTL,
3232279b4e5STianci.Yin 				    RETRY_PERMISSION_OR_INVALID_PAGE_FAULT,
3242279b4e5STianci.Yin 				    !amdgpu_noretry);
3252279b4e5STianci.Yin 		WREG32_SOC15_OFFSET(GC, 0, regGCVM_CONTEXT1_CNTL,
3262279b4e5STianci.Yin 				    i * hub->ctx_distance, tmp);
3272279b4e5STianci.Yin 		WREG32_SOC15_OFFSET(GC, 0, regGCVM_CONTEXT1_PAGE_TABLE_START_ADDR_LO32,
3282279b4e5STianci.Yin 				    i * hub->ctx_addr_distance, 0);
3292279b4e5STianci.Yin 		WREG32_SOC15_OFFSET(GC, 0, regGCVM_CONTEXT1_PAGE_TABLE_START_ADDR_HI32,
3302279b4e5STianci.Yin 				    i * hub->ctx_addr_distance, 0);
3312279b4e5STianci.Yin 		WREG32_SOC15_OFFSET(GC, 0, regGCVM_CONTEXT1_PAGE_TABLE_END_ADDR_LO32,
3322279b4e5STianci.Yin 				    i * hub->ctx_addr_distance,
3332279b4e5STianci.Yin 				    lower_32_bits(adev->vm_manager.max_pfn - 1));
3342279b4e5STianci.Yin 		WREG32_SOC15_OFFSET(GC, 0, regGCVM_CONTEXT1_PAGE_TABLE_END_ADDR_HI32,
3352279b4e5STianci.Yin 				    i * hub->ctx_addr_distance,
3362279b4e5STianci.Yin 				    upper_32_bits(adev->vm_manager.max_pfn - 1));
3372279b4e5STianci.Yin 	}
338*d7dab4fcSJack Xiao 
339*d7dab4fcSJack Xiao 	hub->vm_cntx_cntl = tmp;
3402279b4e5STianci.Yin }
3412279b4e5STianci.Yin 
3422279b4e5STianci.Yin static void gfxhub_v3_0_program_invalidation(struct amdgpu_device *adev)
3432279b4e5STianci.Yin {
3442279b4e5STianci.Yin 	struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB_0];
3452279b4e5STianci.Yin 	unsigned i;
3462279b4e5STianci.Yin 
3472279b4e5STianci.Yin 	for (i = 0 ; i < 18; ++i) {
3482279b4e5STianci.Yin 		WREG32_SOC15_OFFSET(GC, 0, regGCVM_INVALIDATE_ENG0_ADDR_RANGE_LO32,
3492279b4e5STianci.Yin 				    i * hub->eng_addr_distance, 0xffffffff);
3502279b4e5STianci.Yin 		WREG32_SOC15_OFFSET(GC, 0, regGCVM_INVALIDATE_ENG0_ADDR_RANGE_HI32,
3512279b4e5STianci.Yin 				    i * hub->eng_addr_distance, 0x1f);
3522279b4e5STianci.Yin 	}
3532279b4e5STianci.Yin }
3542279b4e5STianci.Yin 
3552279b4e5STianci.Yin static int gfxhub_v3_0_gart_enable(struct amdgpu_device *adev)
3562279b4e5STianci.Yin {
3572279b4e5STianci.Yin 	if (amdgpu_sriov_vf(adev)) {
3582279b4e5STianci.Yin 		/*
3592279b4e5STianci.Yin 		 * GCMC_VM_FB_LOCATION_BASE/TOP is NULL for VF, becuase they are
3602279b4e5STianci.Yin 		 * VF copy registers so vbios post doesn't program them, for
3612279b4e5STianci.Yin 		 * SRIOV driver need to program them
3622279b4e5STianci.Yin 		 */
3632279b4e5STianci.Yin 		WREG32_SOC15(GC, 0, regGCMC_VM_FB_LOCATION_BASE,
3642279b4e5STianci.Yin 			     adev->gmc.vram_start >> 24);
3652279b4e5STianci.Yin 		WREG32_SOC15(GC, 0, regGCMC_VM_FB_LOCATION_TOP,
3662279b4e5STianci.Yin 			     adev->gmc.vram_end >> 24);
3672279b4e5STianci.Yin 	}
3682279b4e5STianci.Yin 
3692279b4e5STianci.Yin 	/* GART Enable. */
3702279b4e5STianci.Yin 	gfxhub_v3_0_init_gart_aperture_regs(adev);
3712279b4e5STianci.Yin 	gfxhub_v3_0_init_system_aperture_regs(adev);
3722279b4e5STianci.Yin 	gfxhub_v3_0_init_tlb_regs(adev);
3732279b4e5STianci.Yin 	gfxhub_v3_0_init_cache_regs(adev);
3742279b4e5STianci.Yin 
3752279b4e5STianci.Yin 	gfxhub_v3_0_enable_system_domain(adev);
3762279b4e5STianci.Yin 	gfxhub_v3_0_disable_identity_aperture(adev);
3772279b4e5STianci.Yin 	gfxhub_v3_0_setup_vmid_config(adev);
3782279b4e5STianci.Yin 	gfxhub_v3_0_program_invalidation(adev);
3792279b4e5STianci.Yin 
3802279b4e5STianci.Yin 	return 0;
3812279b4e5STianci.Yin }
3822279b4e5STianci.Yin 
3832279b4e5STianci.Yin static void gfxhub_v3_0_gart_disable(struct amdgpu_device *adev)
3842279b4e5STianci.Yin {
3852279b4e5STianci.Yin 	struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB_0];
3862279b4e5STianci.Yin 	u32 tmp;
3872279b4e5STianci.Yin 	u32 i;
3882279b4e5STianci.Yin 
3892279b4e5STianci.Yin 	/* Disable all tables */
3902279b4e5STianci.Yin 	for (i = 0; i < 16; i++)
3912279b4e5STianci.Yin 		WREG32_SOC15_OFFSET(GC, 0, regGCVM_CONTEXT0_CNTL,
3922279b4e5STianci.Yin 				    i * hub->ctx_distance, 0);
3932279b4e5STianci.Yin 
3942279b4e5STianci.Yin 	/* Setup TLB control */
3952279b4e5STianci.Yin 	tmp = RREG32_SOC15(GC, 0, regGCMC_VM_MX_L1_TLB_CNTL);
3962279b4e5STianci.Yin 	tmp = REG_SET_FIELD(tmp, GCMC_VM_MX_L1_TLB_CNTL, ENABLE_L1_TLB, 0);
3972279b4e5STianci.Yin 	tmp = REG_SET_FIELD(tmp, GCMC_VM_MX_L1_TLB_CNTL,
3982279b4e5STianci.Yin 			    ENABLE_ADVANCED_DRIVER_MODEL, 0);
3992279b4e5STianci.Yin 	WREG32_SOC15(GC, 0, regGCMC_VM_MX_L1_TLB_CNTL, tmp);
4002279b4e5STianci.Yin 
4012279b4e5STianci.Yin 	/* Setup L2 cache */
4022279b4e5STianci.Yin 	WREG32_FIELD15_PREREG(GC, 0, GCVM_L2_CNTL, ENABLE_L2_CACHE, 0);
4032279b4e5STianci.Yin 	WREG32_SOC15(GC, 0, regGCVM_L2_CNTL3, 0);
4042279b4e5STianci.Yin }
4052279b4e5STianci.Yin 
4062279b4e5STianci.Yin /**
4072279b4e5STianci.Yin  * gfxhub_v3_0_set_fault_enable_default - update GART/VM fault handling
4082279b4e5STianci.Yin  *
4092279b4e5STianci.Yin  * @adev: amdgpu_device pointer
4102279b4e5STianci.Yin  * @value: true redirects VM faults to the default page
4112279b4e5STianci.Yin  */
4122279b4e5STianci.Yin static void gfxhub_v3_0_set_fault_enable_default(struct amdgpu_device *adev,
4132279b4e5STianci.Yin 					  bool value)
4142279b4e5STianci.Yin {
4152279b4e5STianci.Yin 	u32 tmp;
4162279b4e5STianci.Yin 
4172279b4e5STianci.Yin 	/* These registers are not accessible to VF-SRIOV.
4182279b4e5STianci.Yin 	 * The PF will program them instead.
4192279b4e5STianci.Yin 	 */
4202279b4e5STianci.Yin 	if (amdgpu_sriov_vf(adev))
4212279b4e5STianci.Yin 		return;
4222279b4e5STianci.Yin 
4232279b4e5STianci.Yin 	tmp = RREG32_SOC15(GC, 0, regGCVM_L2_PROTECTION_FAULT_CNTL);
4242279b4e5STianci.Yin 	tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
4252279b4e5STianci.Yin 			    RANGE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
4262279b4e5STianci.Yin 	tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
4272279b4e5STianci.Yin 			    PDE0_PROTECTION_FAULT_ENABLE_DEFAULT, value);
4282279b4e5STianci.Yin 	tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
4292279b4e5STianci.Yin 			    PDE1_PROTECTION_FAULT_ENABLE_DEFAULT, value);
4302279b4e5STianci.Yin 	tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
4312279b4e5STianci.Yin 			    PDE2_PROTECTION_FAULT_ENABLE_DEFAULT, value);
4322279b4e5STianci.Yin 	tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
4332279b4e5STianci.Yin 			    TRANSLATE_FURTHER_PROTECTION_FAULT_ENABLE_DEFAULT,
4342279b4e5STianci.Yin 			    value);
4352279b4e5STianci.Yin 	tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
4362279b4e5STianci.Yin 			    NACK_PROTECTION_FAULT_ENABLE_DEFAULT, value);
4372279b4e5STianci.Yin 	tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
4382279b4e5STianci.Yin 			    DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
4392279b4e5STianci.Yin 	tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
4402279b4e5STianci.Yin 			    VALID_PROTECTION_FAULT_ENABLE_DEFAULT, value);
4412279b4e5STianci.Yin 	tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
4422279b4e5STianci.Yin 			    READ_PROTECTION_FAULT_ENABLE_DEFAULT, value);
4432279b4e5STianci.Yin 	tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
4442279b4e5STianci.Yin 			    WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
4452279b4e5STianci.Yin 	tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
4462279b4e5STianci.Yin 			    EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
4472279b4e5STianci.Yin 	if (!value) {
4482279b4e5STianci.Yin 		tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
4492279b4e5STianci.Yin 				CRASH_ON_NO_RETRY_FAULT, 1);
4502279b4e5STianci.Yin 		tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
4512279b4e5STianci.Yin 				CRASH_ON_RETRY_FAULT, 1);
4522279b4e5STianci.Yin 	}
4532279b4e5STianci.Yin 	WREG32_SOC15(GC, 0, regGCVM_L2_PROTECTION_FAULT_CNTL, tmp);
4542279b4e5STianci.Yin }
4552279b4e5STianci.Yin 
4562279b4e5STianci.Yin static const struct amdgpu_vmhub_funcs gfxhub_v3_0_vmhub_funcs = {
4572279b4e5STianci.Yin 	.print_l2_protection_fault_status = gfxhub_v3_0_print_l2_protection_fault_status,
4582279b4e5STianci.Yin 	.get_invalidate_req = gfxhub_v3_0_get_invalidate_req,
4592279b4e5STianci.Yin };
4602279b4e5STianci.Yin 
4612279b4e5STianci.Yin static void gfxhub_v3_0_init(struct amdgpu_device *adev)
4622279b4e5STianci.Yin {
4632279b4e5STianci.Yin 	struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB_0];
4642279b4e5STianci.Yin 
4652279b4e5STianci.Yin 	hub->ctx0_ptb_addr_lo32 =
4662279b4e5STianci.Yin 		SOC15_REG_OFFSET(GC, 0,
4672279b4e5STianci.Yin 				 regGCVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32);
4682279b4e5STianci.Yin 	hub->ctx0_ptb_addr_hi32 =
4692279b4e5STianci.Yin 		SOC15_REG_OFFSET(GC, 0,
4702279b4e5STianci.Yin 				 regGCVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32);
4712279b4e5STianci.Yin 	hub->vm_inv_eng0_sem =
4722279b4e5STianci.Yin 		SOC15_REG_OFFSET(GC, 0, regGCVM_INVALIDATE_ENG0_SEM);
4732279b4e5STianci.Yin 	hub->vm_inv_eng0_req =
4742279b4e5STianci.Yin 		SOC15_REG_OFFSET(GC, 0, regGCVM_INVALIDATE_ENG0_REQ);
4752279b4e5STianci.Yin 	hub->vm_inv_eng0_ack =
4762279b4e5STianci.Yin 		SOC15_REG_OFFSET(GC, 0, regGCVM_INVALIDATE_ENG0_ACK);
4772279b4e5STianci.Yin 	hub->vm_context0_cntl =
4782279b4e5STianci.Yin 		SOC15_REG_OFFSET(GC, 0, regGCVM_CONTEXT0_CNTL);
4792279b4e5STianci.Yin 	hub->vm_l2_pro_fault_status =
4802279b4e5STianci.Yin 		SOC15_REG_OFFSET(GC, 0, regGCVM_L2_PROTECTION_FAULT_STATUS);
4812279b4e5STianci.Yin 	hub->vm_l2_pro_fault_cntl =
4822279b4e5STianci.Yin 		SOC15_REG_OFFSET(GC, 0, regGCVM_L2_PROTECTION_FAULT_CNTL);
4832279b4e5STianci.Yin 
4842279b4e5STianci.Yin 	hub->ctx_distance = regGCVM_CONTEXT1_CNTL - regGCVM_CONTEXT0_CNTL;
4852279b4e5STianci.Yin 	hub->ctx_addr_distance = regGCVM_CONTEXT1_PAGE_TABLE_BASE_ADDR_LO32 -
4862279b4e5STianci.Yin 		regGCVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32;
4872279b4e5STianci.Yin 	hub->eng_distance = regGCVM_INVALIDATE_ENG1_REQ -
4882279b4e5STianci.Yin 		regGCVM_INVALIDATE_ENG0_REQ;
4892279b4e5STianci.Yin 	hub->eng_addr_distance = regGCVM_INVALIDATE_ENG1_ADDR_RANGE_LO32 -
4902279b4e5STianci.Yin 		regGCVM_INVALIDATE_ENG0_ADDR_RANGE_LO32;
4912279b4e5STianci.Yin 
4922279b4e5STianci.Yin 	hub->vm_cntx_cntl_vm_fault = GCVM_CONTEXT1_CNTL__RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK |
4932279b4e5STianci.Yin 		GCVM_CONTEXT1_CNTL__DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK |
4942279b4e5STianci.Yin 		GCVM_CONTEXT1_CNTL__PDE0_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK |
4952279b4e5STianci.Yin 		GCVM_CONTEXT1_CNTL__VALID_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK |
4962279b4e5STianci.Yin 		GCVM_CONTEXT1_CNTL__READ_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK |
4972279b4e5STianci.Yin 		GCVM_CONTEXT1_CNTL__WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK |
4982279b4e5STianci.Yin 		GCVM_CONTEXT1_CNTL__EXECUTE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK;
4992279b4e5STianci.Yin 
5002279b4e5STianci.Yin 	hub->vmhub_funcs = &gfxhub_v3_0_vmhub_funcs;
5012279b4e5STianci.Yin }
5022279b4e5STianci.Yin 
5032279b4e5STianci.Yin const struct amdgpu_gfxhub_funcs gfxhub_v3_0_funcs = {
5042279b4e5STianci.Yin 	.get_fb_location = gfxhub_v3_0_get_fb_location,
5052279b4e5STianci.Yin 	.get_mc_fb_offset = gfxhub_v3_0_get_mc_fb_offset,
5062279b4e5STianci.Yin 	.setup_vm_pt_regs = gfxhub_v3_0_setup_vm_pt_regs,
5072279b4e5STianci.Yin 	.gart_enable = gfxhub_v3_0_gart_enable,
5082279b4e5STianci.Yin 	.gart_disable = gfxhub_v3_0_gart_disable,
5092279b4e5STianci.Yin 	.set_fault_enable_default = gfxhub_v3_0_set_fault_enable_default,
5102279b4e5STianci.Yin 	.init = gfxhub_v3_0_init,
5112279b4e5STianci.Yin };
512