Skip to content
Navigation Menu
Toggle navigation
Sign in
In this repository
All GitHub Enterprise
↵
Jump to
↵
No suggested jump to results
In this repository
All GitHub Enterprise
↵
Jump to
↵
In this organization
All GitHub Enterprise
↵
Jump to
↵
In this repository
All GitHub Enterprise
↵
Jump to
↵
Sign in
Reseting focus
You signed in with another tab or window.
Reload
to refresh your session.
You signed out in another tab or window.
Reload
to refresh your session.
You switched accounts on another tab or window.
Reload
to refresh your session.
Dismiss alert
{{ message }}
mariux64
/
linux
Public
Notifications
You must be signed in to change notification settings
Fork
0
Star
0
Code
Issues
2
Pull requests
0
Actions
Projects
0
Wiki
Security
Insights
Additional navigation options
Code
Issues
Pull requests
Actions
Projects
Wiki
Security
Insights
Files
768b47b
Breadcrumbs
linux
/
drivers
/
gpu
/
drm
/
amd
/
amdgpu
/
soc15.c
Blame
Blame
Latest commit
History
History
1528 lines (1314 loc) · 43.1 KB
Breadcrumbs
linux
/
drivers
/
gpu
/
drm
/
amd
/
amdgpu
/
soc15.c
Top
File metadata and controls
Code
Blame
1528 lines (1314 loc) · 43.1 KB
Raw
/* * Copyright 2016 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * */ #include <linux/firmware.h> #include <linux/slab.h> #include <linux/module.h> #include <linux/pci.h> #include "amdgpu.h" #include "amdgpu_atombios.h" #include "amdgpu_ih.h" #include "amdgpu_uvd.h" #include "amdgpu_vce.h" #include "amdgpu_ucode.h" #include "amdgpu_psp.h" #include "atom.h" #include "amd_pcie.h" #include "uvd/uvd_7_0_offset.h" #include "gc/gc_9_0_offset.h" #include "gc/gc_9_0_sh_mask.h" #include "sdma0/sdma0_4_0_offset.h" #include "sdma1/sdma1_4_0_offset.h" #include "hdp/hdp_4_0_offset.h" #include "hdp/hdp_4_0_sh_mask.h" #include "smuio/smuio_9_0_offset.h" #include "smuio/smuio_9_0_sh_mask.h" #include "nbio/nbio_7_0_default.h" #include "nbio/nbio_7_0_offset.h" #include "nbio/nbio_7_0_sh_mask.h" #include "nbio/nbio_7_0_smn.h" #include "mp/mp_9_0_offset.h" #include "soc15.h" #include "soc15_common.h" #include "gfx_v9_0.h" #include "gmc_v9_0.h" #include "gfxhub_v1_0.h" #include "mmhub_v1_0.h" #include "df_v1_7.h" #include "df_v3_6.h" #include "vega10_ih.h" #include "sdma_v4_0.h" #include "uvd_v7_0.h" #include "vce_v4_0.h" #include "vcn_v1_0.h" #include "vcn_v2_0.h" #include "vcn_v2_5.h" #include "dce_virtual.h" #include "mxgpu_ai.h" #include "amdgpu_smu.h" #include "amdgpu_ras.h" #include "amdgpu_xgmi.h" #include <uapi/linux/kfd_ioctl.h> #define mmMP0_MISC_CGTT_CTRL0 0x01b9 #define mmMP0_MISC_CGTT_CTRL0_BASE_IDX 0 #define mmMP0_MISC_LIGHT_SLEEP_CTRL 0x01ba #define mmMP0_MISC_LIGHT_SLEEP_CTRL_BASE_IDX 0 /* for Vega20 register name change */ #define mmHDP_MEM_POWER_CTRL 0x00d4 #define HDP_MEM_POWER_CTRL__IPH_MEM_POWER_CTRL_EN_MASK 0x00000001L #define HDP_MEM_POWER_CTRL__IPH_MEM_POWER_LS_EN_MASK 0x00000002L #define HDP_MEM_POWER_CTRL__RC_MEM_POWER_CTRL_EN_MASK 0x00010000L #define HDP_MEM_POWER_CTRL__RC_MEM_POWER_LS_EN_MASK 0x00020000L #define mmHDP_MEM_POWER_CTRL_BASE_IDX 0 /* * Indirect registers accessor */ static u32 soc15_pcie_rreg(struct amdgpu_device *adev, u32 reg) { unsigned long flags, address, data; u32 r; address = adev->nbio_funcs->get_pcie_index_offset(adev); data = adev->nbio_funcs->get_pcie_data_offset(adev); spin_lock_irqsave(&adev->pcie_idx_lock, flags); WREG32(address, reg); (void)RREG32(address); r = RREG32(data); spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); return r; } static void soc15_pcie_wreg(struct amdgpu_device *adev, u32 reg, u32 v) { unsigned long flags, address, data; address = adev->nbio_funcs->get_pcie_index_offset(adev); data = adev->nbio_funcs->get_pcie_data_offset(adev); spin_lock_irqsave(&adev->pcie_idx_lock, flags); WREG32(address, reg); (void)RREG32(address); WREG32(data, v); (void)RREG32(data); spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); } static u64 soc15_pcie_rreg64(struct amdgpu_device *adev, u32 reg) { unsigned long flags, address, data; u64 r; address = adev->nbio_funcs->get_pcie_index_offset(adev); data = adev->nbio_funcs->get_pcie_data_offset(adev); spin_lock_irqsave(&adev->pcie_idx_lock, flags); /* read low 32 bit */ WREG32(address, reg); (void)RREG32(address); r = RREG32(data); /* read high 32 bit*/ WREG32(address, reg + 4); (void)RREG32(address); r |= ((u64)RREG32(data) << 32); spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); return r; } static void soc15_pcie_wreg64(struct amdgpu_device *adev, u32 reg, u64 v) { unsigned long flags, address, data; address = adev->nbio_funcs->get_pcie_index_offset(adev); data = adev->nbio_funcs->get_pcie_data_offset(adev); spin_lock_irqsave(&adev->pcie_idx_lock, flags); /* write low 32 bit */ WREG32(address, reg); (void)RREG32(address); WREG32(data, (u32)(v & 0xffffffffULL)); (void)RREG32(data); /* write high 32 bit */ WREG32(address, reg + 4); (void)RREG32(address); WREG32(data, (u32)(v >> 32)); (void)RREG32(data); spin_unlock_irqrestore(&adev->pcie_idx_lock, flags); } static u32 soc15_uvd_ctx_rreg(struct amdgpu_device *adev, u32 reg) { unsigned long flags, address, data; u32 r; address = SOC15_REG_OFFSET(UVD, 0, mmUVD_CTX_INDEX); data = SOC15_REG_OFFSET(UVD, 0, mmUVD_CTX_DATA); spin_lock_irqsave(&adev->uvd_ctx_idx_lock, flags); WREG32(address, ((reg) & 0x1ff)); r = RREG32(data); spin_unlock_irqrestore(&adev->uvd_ctx_idx_lock, flags); return r; } static void soc15_uvd_ctx_wreg(struct amdgpu_device *adev, u32 reg, u32 v) { unsigned long flags, address, data; address = SOC15_REG_OFFSET(UVD, 0, mmUVD_CTX_INDEX); data = SOC15_REG_OFFSET(UVD, 0, mmUVD_CTX_DATA); spin_lock_irqsave(&adev->uvd_ctx_idx_lock, flags); WREG32(address, ((reg) & 0x1ff)); WREG32(data, (v)); spin_unlock_irqrestore(&adev->uvd_ctx_idx_lock, flags); } static u32 soc15_didt_rreg(struct amdgpu_device *adev, u32 reg) { unsigned long flags, address, data; u32 r; address = SOC15_REG_OFFSET(GC, 0, mmDIDT_IND_INDEX); data = SOC15_REG_OFFSET(GC, 0, mmDIDT_IND_DATA); spin_lock_irqsave(&adev->didt_idx_lock, flags); WREG32(address, (reg)); r = RREG32(data); spin_unlock_irqrestore(&adev->didt_idx_lock, flags); return r; } static void soc15_didt_wreg(struct amdgpu_device *adev, u32 reg, u32 v) { unsigned long flags, address, data; address = SOC15_REG_OFFSET(GC, 0, mmDIDT_IND_INDEX); data = SOC15_REG_OFFSET(GC, 0, mmDIDT_IND_DATA); spin_lock_irqsave(&adev->didt_idx_lock, flags); WREG32(address, (reg)); WREG32(data, (v)); spin_unlock_irqrestore(&adev->didt_idx_lock, flags); } static u32 soc15_gc_cac_rreg(struct amdgpu_device *adev, u32 reg) { unsigned long flags; u32 r; spin_lock_irqsave(&adev->gc_cac_idx_lock, flags); WREG32_SOC15(GC, 0, mmGC_CAC_IND_INDEX, (reg)); r = RREG32_SOC15(GC, 0, mmGC_CAC_IND_DATA); spin_unlock_irqrestore(&adev->gc_cac_idx_lock, flags); return r; } static void soc15_gc_cac_wreg(struct amdgpu_device *adev, u32 reg, u32 v) { unsigned long flags; spin_lock_irqsave(&adev->gc_cac_idx_lock, flags); WREG32_SOC15(GC, 0, mmGC_CAC_IND_INDEX, (reg)); WREG32_SOC15(GC, 0, mmGC_CAC_IND_DATA, (v)); spin_unlock_irqrestore(&adev->gc_cac_idx_lock, flags); } static u32 soc15_se_cac_rreg(struct amdgpu_device *adev, u32 reg) { unsigned long flags; u32 r; spin_lock_irqsave(&adev->se_cac_idx_lock, flags); WREG32_SOC15(GC, 0, mmSE_CAC_IND_INDEX, (reg)); r = RREG32_SOC15(GC, 0, mmSE_CAC_IND_DATA); spin_unlock_irqrestore(&adev->se_cac_idx_lock, flags); return r; } static void soc15_se_cac_wreg(struct amdgpu_device *adev, u32 reg, u32 v) { unsigned long flags; spin_lock_irqsave(&adev->se_cac_idx_lock, flags); WREG32_SOC15(GC, 0, mmSE_CAC_IND_INDEX, (reg)); WREG32_SOC15(GC, 0, mmSE_CAC_IND_DATA, (v)); spin_unlock_irqrestore(&adev->se_cac_idx_lock, flags); } static u32 soc15_get_config_memsize(struct amdgpu_device *adev) { return adev->nbio_funcs->get_memsize(adev); } static u32 soc15_get_xclk(struct amdgpu_device *adev) { return adev->clock.spll.reference_freq; } void soc15_grbm_select(struct amdgpu_device *adev, u32 me, u32 pipe, u32 queue, u32 vmid) { u32 grbm_gfx_cntl = 0; grbm_gfx_cntl = REG_SET_FIELD(grbm_gfx_cntl, GRBM_GFX_CNTL, PIPEID, pipe); grbm_gfx_cntl = REG_SET_FIELD(grbm_gfx_cntl, GRBM_GFX_CNTL, MEID, me); grbm_gfx_cntl = REG_SET_FIELD(grbm_gfx_cntl, GRBM_GFX_CNTL, VMID, vmid); grbm_gfx_cntl = REG_SET_FIELD(grbm_gfx_cntl, GRBM_GFX_CNTL, QUEUEID, queue); WREG32_SOC15_RLC_SHADOW(GC, 0, mmGRBM_GFX_CNTL, grbm_gfx_cntl); } static void soc15_vga_set_state(struct amdgpu_device *adev, bool state) { /* todo */ } static bool soc15_read_disabled_bios(struct amdgpu_device *adev) { /* todo */ return false; } static bool soc15_read_bios_from_rom(struct amdgpu_device *adev, u8 *bios, u32 length_bytes) { u32 *dw_ptr; u32 i, length_dw; if (bios == NULL) return false; if (length_bytes == 0) return false; /* APU vbios image is part of sbios image */ if (adev->flags & AMD_IS_APU) return false; dw_ptr = (u32 *)bios; length_dw = ALIGN(length_bytes, 4) / 4; /* set rom index to 0 */ WREG32(SOC15_REG_OFFSET(SMUIO, 0, mmROM_INDEX), 0); /* read out the rom data */ for (i = 0; i < length_dw; i++) dw_ptr[i] = RREG32(SOC15_REG_OFFSET(SMUIO, 0, mmROM_DATA)); return true; } static struct soc15_allowed_register_entry soc15_allowed_read_registers[] = { { SOC15_REG_ENTRY(GC, 0, mmGRBM_STATUS)}, { SOC15_REG_ENTRY(GC, 0, mmGRBM_STATUS2)}, { SOC15_REG_ENTRY(GC, 0, mmGRBM_STATUS_SE0)}, { SOC15_REG_ENTRY(GC, 0, mmGRBM_STATUS_SE1)}, { SOC15_REG_ENTRY(GC, 0, mmGRBM_STATUS_SE2)}, { SOC15_REG_ENTRY(GC, 0, mmGRBM_STATUS_SE3)}, { SOC15_REG_ENTRY(SDMA0, 0, mmSDMA0_STATUS_REG)}, { SOC15_REG_ENTRY(SDMA1, 0, mmSDMA1_STATUS_REG)}, { SOC15_REG_ENTRY(GC, 0, mmCP_STAT)}, { SOC15_REG_ENTRY(GC, 0, mmCP_STALLED_STAT1)}, { SOC15_REG_ENTRY(GC, 0, mmCP_STALLED_STAT2)}, { SOC15_REG_ENTRY(GC, 0, mmCP_STALLED_STAT3)}, { SOC15_REG_ENTRY(GC, 0, mmCP_CPF_BUSY_STAT)}, { SOC15_REG_ENTRY(GC, 0, mmCP_CPF_STALLED_STAT1)}, { SOC15_REG_ENTRY(GC, 0, mmCP_CPF_STATUS)}, { SOC15_REG_ENTRY(GC, 0, mmCP_CPC_STALLED_STAT1)}, { SOC15_REG_ENTRY(GC, 0, mmCP_CPC_STATUS)}, { SOC15_REG_ENTRY(GC, 0, mmGB_ADDR_CONFIG)}, { SOC15_REG_ENTRY(GC, 0, mmDB_DEBUG2)}, }; static uint32_t soc15_read_indexed_register(struct amdgpu_device *adev, u32 se_num, u32 sh_num, u32 reg_offset) { uint32_t val; mutex_lock(&adev->grbm_idx_mutex); if (se_num != 0xffffffff || sh_num != 0xffffffff) amdgpu_gfx_select_se_sh(adev, se_num, sh_num, 0xffffffff); val = RREG32(reg_offset); if (se_num != 0xffffffff || sh_num != 0xffffffff) amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); mutex_unlock(&adev->grbm_idx_mutex); return val; } static uint32_t soc15_get_register_value(struct amdgpu_device *adev, bool indexed, u32 se_num, u32 sh_num, u32 reg_offset) { if (indexed) { return soc15_read_indexed_register(adev, se_num, sh_num, reg_offset); } else { if (reg_offset == SOC15_REG_OFFSET(GC, 0, mmGB_ADDR_CONFIG)) return adev->gfx.config.gb_addr_config; else if (reg_offset == SOC15_REG_OFFSET(GC, 0, mmDB_DEBUG2)) return adev->gfx.config.db_debug2; return RREG32(reg_offset); } } static int soc15_read_register(struct amdgpu_device *adev, u32 se_num, u32 sh_num, u32 reg_offset, u32 *value) { uint32_t i; struct soc15_allowed_register_entry *en; *value = 0; for (i = 0; i < ARRAY_SIZE(soc15_allowed_read_registers); i++) { en = &soc15_allowed_read_registers[i]; if (reg_offset != (adev->reg_offset[en->hwip][en->inst][en->seg] + en->reg_offset)) continue; *value = soc15_get_register_value(adev, soc15_allowed_read_registers[i].grbm_indexed, se_num, sh_num, reg_offset); return 0; } return -EINVAL; } /** * soc15_program_register_sequence - program an array of registers. * * @adev: amdgpu_device pointer * @regs: pointer to the register array * @array_size: size of the register array * * Programs an array or registers with and and or masks. * This is a helper for setting golden registers. */ void soc15_program_register_sequence(struct amdgpu_device *adev, const struct soc15_reg_golden *regs, const u32 array_size) { const struct soc15_reg_golden *entry; u32 tmp, reg; int i; for (i = 0; i < array_size; ++i) { entry = ®s[i]; reg = adev->reg_offset[entry->hwip][entry->instance][entry->segment] + entry->reg; if (entry->and_mask == 0xffffffff) { tmp = entry->or_mask; } else { tmp = RREG32(reg); tmp &= ~(entry->and_mask); tmp |= (entry->or_mask & entry->and_mask); } if (reg == SOC15_REG_OFFSET(GC, 0, mmPA_SC_BINNER_EVENT_CNTL_3) || reg == SOC15_REG_OFFSET(GC, 0, mmPA_SC_ENHANCE) || reg == SOC15_REG_OFFSET(GC, 0, mmPA_SC_ENHANCE_1) || reg == SOC15_REG_OFFSET(GC, 0, mmSH_MEM_CONFIG)) WREG32_RLC(reg, tmp); else WREG32(reg, tmp); } } static int soc15_asic_mode1_reset(struct amdgpu_device *adev) { u32 i; int ret = 0; amdgpu_atombios_scratch_regs_engine_hung(adev, true); dev_info(adev->dev, "GPU mode1 reset\n"); /* disable BM */ pci_clear_master(adev->pdev); pci_save_state(adev->pdev); ret = psp_gpu_reset(adev); if (ret) dev_err(adev->dev, "GPU mode1 reset failed\n"); pci_restore_state(adev->pdev); /* wait for asic to come out of reset */ for (i = 0; i < adev->usec_timeout; i++) { u32 memsize = adev->nbio_funcs->get_memsize(adev); if (memsize != 0xffffffff) break; udelay(1); } amdgpu_atombios_scratch_regs_engine_hung(adev, false); return ret; } static int soc15_asic_get_baco_capability(struct amdgpu_device *adev, bool *cap) { void *pp_handle = adev->powerplay.pp_handle; const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; if (!pp_funcs || !pp_funcs->get_asic_baco_capability) { *cap = false; return -ENOENT; } return pp_funcs->get_asic_baco_capability(pp_handle, cap); } static int soc15_asic_baco_reset(struct amdgpu_device *adev) { void *pp_handle = adev->powerplay.pp_handle; const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; if (!pp_funcs ||!pp_funcs->get_asic_baco_state ||!pp_funcs->set_asic_baco_state) return -ENOENT; /* enter BACO state */ if (pp_funcs->set_asic_baco_state(pp_handle, 1)) return -EIO; /* exit BACO state */ if (pp_funcs->set_asic_baco_state(pp_handle, 0)) return -EIO; dev_info(adev->dev, "GPU BACO reset\n"); adev->in_baco_reset = 1; return 0; } static int soc15_mode2_reset(struct amdgpu_device *adev) { if (!adev->powerplay.pp_funcs || !adev->powerplay.pp_funcs->asic_reset_mode_2) return -ENOENT; return adev->powerplay.pp_funcs->asic_reset_mode_2(adev->powerplay.pp_handle); } static enum amd_reset_method soc15_asic_reset_method(struct amdgpu_device *adev) { bool baco_reset; switch (adev->asic_type) { case CHIP_RAVEN: return AMD_RESET_METHOD_MODE2; case CHIP_VEGA10: case CHIP_VEGA12: soc15_asic_get_baco_capability(adev, &baco_reset); break; case CHIP_VEGA20: if (adev->psp.sos_fw_version >= 0x80067) soc15_asic_get_baco_capability(adev, &baco_reset); else baco_reset = false; if (baco_reset) { struct amdgpu_hive_info *hive = amdgpu_get_xgmi_hive(adev, 0); struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); if (hive || (ras && ras->supported)) baco_reset = false; } break; default: baco_reset = false; break; } if (baco_reset) return AMD_RESET_METHOD_BACO; else return AMD_RESET_METHOD_MODE1; } static int soc15_asic_reset(struct amdgpu_device *adev) { switch (soc15_asic_reset_method(adev)) { case AMD_RESET_METHOD_BACO: if (!adev->in_suspend) amdgpu_inc_vram_lost(adev); return soc15_asic_baco_reset(adev); case AMD_RESET_METHOD_MODE2: return soc15_mode2_reset(adev); default: if (!adev->in_suspend) amdgpu_inc_vram_lost(adev); return soc15_asic_mode1_reset(adev); } } /*static int soc15_set_uvd_clock(struct amdgpu_device *adev, u32 clock, u32 cntl_reg, u32 status_reg) { return 0; }*/ static int soc15_set_uvd_clocks(struct amdgpu_device *adev, u32 vclk, u32 dclk) { /*int r; r = soc15_set_uvd_clock(adev, vclk, ixCG_VCLK_CNTL, ixCG_VCLK_STATUS); if (r) return r; r = soc15_set_uvd_clock(adev, dclk, ixCG_DCLK_CNTL, ixCG_DCLK_STATUS); */ return 0; } static int soc15_set_vce_clocks(struct amdgpu_device *adev, u32 evclk, u32 ecclk) { /* todo */ return 0; } static void soc15_pcie_gen3_enable(struct amdgpu_device *adev) { if (pci_is_root_bus(adev->pdev->bus)) return; if (amdgpu_pcie_gen2 == 0) return; if (adev->flags & AMD_IS_APU) return; if (!(adev->pm.pcie_gen_mask & (CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2 | CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3))) return; /* todo */ } static void soc15_program_aspm(struct amdgpu_device *adev) { if (amdgpu_aspm == 0) return; /* todo */ } static void soc15_enable_doorbell_aperture(struct amdgpu_device *adev, bool enable) { adev->nbio_funcs->enable_doorbell_aperture(adev, enable); adev->nbio_funcs->enable_doorbell_selfring_aperture(adev, enable); } static const struct amdgpu_ip_block_version vega10_common_ip_block = { .type = AMD_IP_BLOCK_TYPE_COMMON, .major = 2, .minor = 0, .rev = 0, .funcs = &soc15_common_ip_funcs, }; static uint32_t soc15_get_rev_id(struct amdgpu_device *adev) { return adev->nbio_funcs->get_rev_id(adev); } int soc15_set_ip_blocks(struct amdgpu_device *adev) { /* Set IP register base before any HW register access */ switch (adev->asic_type) { case CHIP_VEGA10: case CHIP_VEGA12: case CHIP_RAVEN: case CHIP_RENOIR: vega10_reg_base_init(adev); break; case CHIP_VEGA20: vega20_reg_base_init(adev); break; case CHIP_ARCTURUS: arct_reg_base_init(adev); break; default: return -EINVAL; } if (adev->asic_type == CHIP_VEGA20 || adev->asic_type == CHIP_ARCTURUS) adev->gmc.xgmi.supported = true; if (adev->flags & AMD_IS_APU) adev->nbio_funcs = &nbio_v7_0_funcs; else if (adev->asic_type == CHIP_VEGA20 || adev->asic_type == CHIP_ARCTURUS) adev->nbio_funcs = &nbio_v7_4_funcs; else adev->nbio_funcs = &nbio_v6_1_funcs; if (adev->asic_type == CHIP_VEGA20 || adev->asic_type == CHIP_ARCTURUS) adev->df_funcs = &df_v3_6_funcs; else adev->df_funcs = &df_v1_7_funcs; adev->rev_id = soc15_get_rev_id(adev); adev->nbio_funcs->detect_hw_virt(adev); if (amdgpu_sriov_vf(adev)) adev->virt.ops = &xgpu_ai_virt_ops; switch (adev->asic_type) { case CHIP_VEGA10: case CHIP_VEGA12: case CHIP_VEGA20: amdgpu_device_ip_block_add(adev, &vega10_common_ip_block); amdgpu_device_ip_block_add(adev, &gmc_v9_0_ip_block); /* For Vega10 SR-IOV, PSP need to be initialized before IH */ if (amdgpu_sriov_vf(adev)) { if (likely(adev->firmware.load_type == AMDGPU_FW_LOAD_PSP)) { if (adev->asic_type == CHIP_VEGA20) amdgpu_device_ip_block_add(adev, &psp_v11_0_ip_block); else amdgpu_device_ip_block_add(adev, &psp_v3_1_ip_block); } amdgpu_device_ip_block_add(adev, &vega10_ih_ip_block); } else { amdgpu_device_ip_block_add(adev, &vega10_ih_ip_block); if (likely(adev->firmware.load_type == AMDGPU_FW_LOAD_PSP)) { if (adev->asic_type == CHIP_VEGA20) amdgpu_device_ip_block_add(adev, &psp_v11_0_ip_block); else amdgpu_device_ip_block_add(adev, &psp_v3_1_ip_block); } } amdgpu_device_ip_block_add(adev, &gfx_v9_0_ip_block); amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block); if (!amdgpu_sriov_vf(adev)) { if (is_support_sw_smu(adev)) amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block); else amdgpu_device_ip_block_add(adev, &pp_smu_ip_block); } if (adev->enable_virtual_display || amdgpu_sriov_vf(adev)) amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block); #if defined(CONFIG_DRM_AMD_DC) else if (amdgpu_device_has_dc_support(adev)) amdgpu_device_ip_block_add(adev, &dm_ip_block); #endif if (!(adev->asic_type == CHIP_VEGA20 && amdgpu_sriov_vf(adev))) { amdgpu_device_ip_block_add(adev, &uvd_v7_0_ip_block); amdgpu_device_ip_block_add(adev, &vce_v4_0_ip_block); } break; case CHIP_RAVEN: amdgpu_device_ip_block_add(adev, &vega10_common_ip_block); amdgpu_device_ip_block_add(adev, &gmc_v9_0_ip_block); amdgpu_device_ip_block_add(adev, &vega10_ih_ip_block); if (likely(adev->firmware.load_type == AMDGPU_FW_LOAD_PSP)) amdgpu_device_ip_block_add(adev, &psp_v10_0_ip_block); amdgpu_device_ip_block_add(adev, &gfx_v9_0_ip_block); amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block); amdgpu_device_ip_block_add(adev, &pp_smu_ip_block); if (adev->enable_virtual_display || amdgpu_sriov_vf(adev)) amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block); #if defined(CONFIG_DRM_AMD_DC) else if (amdgpu_device_has_dc_support(adev)) amdgpu_device_ip_block_add(adev, &dm_ip_block); #endif amdgpu_device_ip_block_add(adev, &vcn_v1_0_ip_block); break; case CHIP_ARCTURUS: amdgpu_device_ip_block_add(adev, &vega10_common_ip_block); amdgpu_device_ip_block_add(adev, &gmc_v9_0_ip_block); amdgpu_device_ip_block_add(adev, &vega10_ih_ip_block); if (adev->enable_virtual_display || amdgpu_sriov_vf(adev)) amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block); amdgpu_device_ip_block_add(adev, &gfx_v9_0_ip_block); amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block); amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block); amdgpu_device_ip_block_add(adev, &vcn_v2_5_ip_block); break; case CHIP_RENOIR: amdgpu_device_ip_block_add(adev, &vega10_common_ip_block); amdgpu_device_ip_block_add(adev, &gmc_v9_0_ip_block); amdgpu_device_ip_block_add(adev, &vega10_ih_ip_block); if (likely(adev->firmware.load_type == AMDGPU_FW_LOAD_PSP)) amdgpu_device_ip_block_add(adev, &psp_v12_0_ip_block); if (is_support_sw_smu(adev)) amdgpu_device_ip_block_add(adev, &smu_v12_0_ip_block); amdgpu_device_ip_block_add(adev, &gfx_v9_0_ip_block); amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block); if (adev->enable_virtual_display || amdgpu_sriov_vf(adev)) amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block); #if defined(CONFIG_DRM_AMD_DC) else if (amdgpu_device_has_dc_support(adev)) amdgpu_device_ip_block_add(adev, &dm_ip_block); #endif amdgpu_device_ip_block_add(adev, &vcn_v2_0_ip_block); break; default: return -EINVAL; } return 0; } static void soc15_flush_hdp(struct amdgpu_device *adev, struct amdgpu_ring *ring) { adev->nbio_funcs->hdp_flush(adev, ring); } static void soc15_invalidate_hdp(struct amdgpu_device *adev, struct amdgpu_ring *ring) { if (!ring || !ring->funcs->emit_wreg) WREG32_SOC15_NO_KIQ(HDP, 0, mmHDP_READ_CACHE_INVALIDATE, 1); else amdgpu_ring_emit_wreg(ring, SOC15_REG_OFFSET( HDP, 0, mmHDP_READ_CACHE_INVALIDATE), 1); } static bool soc15_need_full_reset(struct amdgpu_device *adev) { /* change this when we implement soft reset */ return true; } static void soc15_get_pcie_usage(struct amdgpu_device *adev, uint64_t *count0, uint64_t *count1) { uint32_t perfctr = 0; uint64_t cnt0_of, cnt1_of; int tmp; /* This reports 0 on APUs, so return to avoid writing/reading registers * that may or may not be different from their GPU counterparts */ if (adev->flags & AMD_IS_APU) return; /* Set the 2 events that we wish to watch, defined above */ /* Reg 40 is # received msgs */ /* Reg 104 is # of posted requests sent */ perfctr = REG_SET_FIELD(perfctr, PCIE_PERF_CNTL_TXCLK, EVENT0_SEL, 40); perfctr = REG_SET_FIELD(perfctr, PCIE_PERF_CNTL_TXCLK, EVENT1_SEL, 104); /* Write to enable desired perf counters */ WREG32_PCIE(smnPCIE_PERF_CNTL_TXCLK, perfctr); /* Zero out and enable the perf counters * Write 0x5: * Bit 0 = Start all counters(1) * Bit 2 = Global counter reset enable(1) */ WREG32_PCIE(smnPCIE_PERF_COUNT_CNTL, 0x00000005); msleep(1000); /* Load the shadow and disable the perf counters * Write 0x2: * Bit 0 = Stop counters(0) * Bit 1 = Load the shadow counters(1) */ WREG32_PCIE(smnPCIE_PERF_COUNT_CNTL, 0x00000002); /* Read register values to get any >32bit overflow */ tmp = RREG32_PCIE(smnPCIE_PERF_CNTL_TXCLK); cnt0_of = REG_GET_FIELD(tmp, PCIE_PERF_CNTL_TXCLK, COUNTER0_UPPER); cnt1_of = REG_GET_FIELD(tmp, PCIE_PERF_CNTL_TXCLK, COUNTER1_UPPER); /* Get the values and add the overflow */ *count0 = RREG32_PCIE(smnPCIE_PERF_COUNT0_TXCLK) | (cnt0_of << 32); *count1 = RREG32_PCIE(smnPCIE_PERF_COUNT1_TXCLK) | (cnt1_of << 32); } static void vega20_get_pcie_usage(struct amdgpu_device *adev, uint64_t *count0, uint64_t *count1) { uint32_t perfctr = 0; uint64_t cnt0_of, cnt1_of; int tmp; /* This reports 0 on APUs, so return to avoid writing/reading registers * that may or may not be different from their GPU counterparts */ if (adev->flags & AMD_IS_APU) return; /* Set the 2 events that we wish to watch, defined above */ /* Reg 40 is # received msgs */ /* Reg 108 is # of posted requests sent on VG20 */ perfctr = REG_SET_FIELD(perfctr, PCIE_PERF_CNTL_TXCLK3, EVENT0_SEL, 40); perfctr = REG_SET_FIELD(perfctr, PCIE_PERF_CNTL_TXCLK3, EVENT1_SEL, 108); /* Write to enable desired perf counters */ WREG32_PCIE(smnPCIE_PERF_CNTL_TXCLK3, perfctr); /* Zero out and enable the perf counters * Write 0x5: * Bit 0 = Start all counters(1) * Bit 2 = Global counter reset enable(1) */ WREG32_PCIE(smnPCIE_PERF_COUNT_CNTL, 0x00000005); msleep(1000); /* Load the shadow and disable the perf counters * Write 0x2: * Bit 0 = Stop counters(0) * Bit 1 = Load the shadow counters(1) */ WREG32_PCIE(smnPCIE_PERF_COUNT_CNTL, 0x00000002); /* Read register values to get any >32bit overflow */ tmp = RREG32_PCIE(smnPCIE_PERF_CNTL_TXCLK3); cnt0_of = REG_GET_FIELD(tmp, PCIE_PERF_CNTL_TXCLK3, COUNTER0_UPPER); cnt1_of = REG_GET_FIELD(tmp, PCIE_PERF_CNTL_TXCLK3, COUNTER1_UPPER); /* Get the values and add the overflow */ *count0 = RREG32_PCIE(smnPCIE_PERF_COUNT0_TXCLK3) | (cnt0_of << 32); *count1 = RREG32_PCIE(smnPCIE_PERF_COUNT1_TXCLK3) | (cnt1_of << 32); } static bool soc15_need_reset_on_init(struct amdgpu_device *adev) { u32 sol_reg; /* Just return false for soc15 GPUs. Reset does not seem to * be necessary. */ if (!amdgpu_passthrough(adev)) return false; if (adev->flags & AMD_IS_APU) return false; /* Check sOS sign of life register to confirm sys driver and sOS * are already been loaded. */ sol_reg = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_81); if (sol_reg) return true; return false; } static uint64_t soc15_get_pcie_replay_count(struct amdgpu_device *adev) { uint64_t nak_r, nak_g; /* Get the number of NAKs received and generated */ nak_r = RREG32_PCIE(smnPCIE_RX_NUM_NAK); nak_g = RREG32_PCIE(smnPCIE_RX_NUM_NAK_GENERATED); /* Add the total number of NAKs, i.e the number of replays */ return (nak_r + nak_g); } static const struct amdgpu_asic_funcs soc15_asic_funcs = { .read_disabled_bios = &soc15_read_disabled_bios, .read_bios_from_rom = &soc15_read_bios_from_rom, .read_register = &soc15_read_register, .reset = &soc15_asic_reset, .reset_method = &soc15_asic_reset_method, .set_vga_state = &soc15_vga_set_state, .get_xclk = &soc15_get_xclk, .set_uvd_clocks = &soc15_set_uvd_clocks, .set_vce_clocks = &soc15_set_vce_clocks, .get_config_memsize = &soc15_get_config_memsize, .flush_hdp = &soc15_flush_hdp, .invalidate_hdp = &soc15_invalidate_hdp, .need_full_reset = &soc15_need_full_reset, .init_doorbell_index = &vega10_doorbell_index_init, .get_pcie_usage = &soc15_get_pcie_usage, .need_reset_on_init = &soc15_need_reset_on_init, .get_pcie_replay_count = &soc15_get_pcie_replay_count, }; static const struct amdgpu_asic_funcs vega20_asic_funcs = { .read_disabled_bios = &soc15_read_disabled_bios, .read_bios_from_rom = &soc15_read_bios_from_rom, .read_register = &soc15_read_register, .reset = &soc15_asic_reset, .set_vga_state = &soc15_vga_set_state, .get_xclk = &soc15_get_xclk, .set_uvd_clocks = &soc15_set_uvd_clocks, .set_vce_clocks = &soc15_set_vce_clocks, .get_config_memsize = &soc15_get_config_memsize, .flush_hdp = &soc15_flush_hdp, .invalidate_hdp = &soc15_invalidate_hdp, .need_full_reset = &soc15_need_full_reset, .init_doorbell_index = &vega20_doorbell_index_init, .get_pcie_usage = &vega20_get_pcie_usage, .need_reset_on_init = &soc15_need_reset_on_init, .get_pcie_replay_count = &soc15_get_pcie_replay_count, .reset_method = &soc15_asic_reset_method }; static int soc15_common_early_init(void *handle) { #define MMIO_REG_HOLE_OFFSET (0x80000 - PAGE_SIZE) struct amdgpu_device *adev = (struct amdgpu_device *)handle; adev->rmmio_remap.reg_offset = MMIO_REG_HOLE_OFFSET; adev->rmmio_remap.bus_addr = adev->rmmio_base + MMIO_REG_HOLE_OFFSET; adev->smc_rreg = NULL; adev->smc_wreg = NULL; adev->pcie_rreg = &soc15_pcie_rreg; adev->pcie_wreg = &soc15_pcie_wreg; adev->pcie_rreg64 = &soc15_pcie_rreg64; adev->pcie_wreg64 = &soc15_pcie_wreg64; adev->uvd_ctx_rreg = &soc15_uvd_ctx_rreg; adev->uvd_ctx_wreg = &soc15_uvd_ctx_wreg; adev->didt_rreg = &soc15_didt_rreg; adev->didt_wreg = &soc15_didt_wreg; adev->gc_cac_rreg = &soc15_gc_cac_rreg; adev->gc_cac_wreg = &soc15_gc_cac_wreg; adev->se_cac_rreg = &soc15_se_cac_rreg; adev->se_cac_wreg = &soc15_se_cac_wreg; adev->external_rev_id = 0xFF; switch (adev->asic_type) { case CHIP_VEGA10: adev->asic_funcs = &soc15_asic_funcs; adev->cg_flags = AMD_CG_SUPPORT_GFX_MGCG | AMD_CG_SUPPORT_GFX_MGLS | AMD_CG_SUPPORT_GFX_RLC_LS | AMD_CG_SUPPORT_GFX_CP_LS | AMD_CG_SUPPORT_GFX_3D_CGCG | AMD_CG_SUPPORT_GFX_3D_CGLS | AMD_CG_SUPPORT_GFX_CGCG | AMD_CG_SUPPORT_GFX_CGLS | AMD_CG_SUPPORT_BIF_MGCG | AMD_CG_SUPPORT_BIF_LS | AMD_CG_SUPPORT_HDP_LS | AMD_CG_SUPPORT_DRM_MGCG | AMD_CG_SUPPORT_DRM_LS | AMD_CG_SUPPORT_ROM_MGCG | AMD_CG_SUPPORT_DF_MGCG | AMD_CG_SUPPORT_SDMA_MGCG | AMD_CG_SUPPORT_SDMA_LS | AMD_CG_SUPPORT_MC_MGCG | AMD_CG_SUPPORT_MC_LS; adev->pg_flags = 0; adev->external_rev_id = 0x1; break; case CHIP_VEGA12: adev->asic_funcs = &soc15_asic_funcs; adev->cg_flags = AMD_CG_SUPPORT_GFX_MGCG | AMD_CG_SUPPORT_GFX_MGLS | AMD_CG_SUPPORT_GFX_CGCG | AMD_CG_SUPPORT_GFX_CGLS | AMD_CG_SUPPORT_GFX_3D_CGCG | AMD_CG_SUPPORT_GFX_3D_CGLS | AMD_CG_SUPPORT_GFX_CP_LS | AMD_CG_SUPPORT_MC_LS | AMD_CG_SUPPORT_MC_MGCG | AMD_CG_SUPPORT_SDMA_MGCG | AMD_CG_SUPPORT_SDMA_LS | AMD_CG_SUPPORT_BIF_MGCG | AMD_CG_SUPPORT_BIF_LS | AMD_CG_SUPPORT_HDP_MGCG | AMD_CG_SUPPORT_HDP_LS | AMD_CG_SUPPORT_ROM_MGCG | AMD_CG_SUPPORT_VCE_MGCG | AMD_CG_SUPPORT_UVD_MGCG; adev->pg_flags = 0; adev->external_rev_id = adev->rev_id + 0x14; break; case CHIP_VEGA20: adev->asic_funcs = &vega20_asic_funcs; adev->cg_flags = AMD_CG_SUPPORT_GFX_MGCG | AMD_CG_SUPPORT_GFX_MGLS | AMD_CG_SUPPORT_GFX_CGCG | AMD_CG_SUPPORT_GFX_CGLS | AMD_CG_SUPPORT_GFX_3D_CGCG | AMD_CG_SUPPORT_GFX_3D_CGLS | AMD_CG_SUPPORT_GFX_CP_LS | AMD_CG_SUPPORT_MC_LS | AMD_CG_SUPPORT_MC_MGCG | AMD_CG_SUPPORT_SDMA_MGCG | AMD_CG_SUPPORT_SDMA_LS | AMD_CG_SUPPORT_BIF_MGCG | AMD_CG_SUPPORT_BIF_LS | AMD_CG_SUPPORT_HDP_MGCG | AMD_CG_SUPPORT_HDP_LS | AMD_CG_SUPPORT_ROM_MGCG | AMD_CG_SUPPORT_VCE_MGCG | AMD_CG_SUPPORT_UVD_MGCG; adev->pg_flags = 0; adev->external_rev_id = adev->rev_id + 0x28; break; case CHIP_RAVEN: adev->asic_funcs = &soc15_asic_funcs; if (adev->rev_id >= 0x8) adev->external_rev_id = adev->rev_id + 0x79; else if (adev->pdev->device == 0x15d8) adev->external_rev_id = adev->rev_id + 0x41; else if (adev->rev_id == 1) adev->external_rev_id = adev->rev_id + 0x20; else adev->external_rev_id = adev->rev_id + 0x01; if (adev->rev_id >= 0x8) { adev->cg_flags = AMD_CG_SUPPORT_GFX_MGCG | AMD_CG_SUPPORT_GFX_MGLS | AMD_CG_SUPPORT_GFX_CP_LS | AMD_CG_SUPPORT_GFX_3D_CGCG | AMD_CG_SUPPORT_GFX_3D_CGLS | AMD_CG_SUPPORT_GFX_CGCG | AMD_CG_SUPPORT_GFX_CGLS | AMD_CG_SUPPORT_BIF_LS | AMD_CG_SUPPORT_HDP_LS | AMD_CG_SUPPORT_ROM_MGCG | AMD_CG_SUPPORT_MC_MGCG | AMD_CG_SUPPORT_MC_LS | AMD_CG_SUPPORT_SDMA_MGCG | AMD_CG_SUPPORT_SDMA_LS | AMD_CG_SUPPORT_VCN_MGCG; adev->pg_flags = AMD_PG_SUPPORT_SDMA | AMD_PG_SUPPORT_VCN; } else if (adev->pdev->device == 0x15d8) { adev->cg_flags = AMD_CG_SUPPORT_GFX_MGCG | AMD_CG_SUPPORT_GFX_MGLS | AMD_CG_SUPPORT_GFX_CP_LS | AMD_CG_SUPPORT_GFX_3D_CGCG | AMD_CG_SUPPORT_GFX_3D_CGLS | AMD_CG_SUPPORT_GFX_CGCG | AMD_CG_SUPPORT_GFX_CGLS | AMD_CG_SUPPORT_BIF_LS | AMD_CG_SUPPORT_HDP_LS | AMD_CG_SUPPORT_ROM_MGCG | AMD_CG_SUPPORT_MC_MGCG | AMD_CG_SUPPORT_MC_LS | AMD_CG_SUPPORT_SDMA_MGCG | AMD_CG_SUPPORT_SDMA_LS; adev->pg_flags = AMD_PG_SUPPORT_SDMA | AMD_PG_SUPPORT_MMHUB | AMD_PG_SUPPORT_VCN | AMD_PG_SUPPORT_VCN_DPG; } else { adev->cg_flags = AMD_CG_SUPPORT_GFX_MGCG | AMD_CG_SUPPORT_GFX_MGLS | AMD_CG_SUPPORT_GFX_RLC_LS | AMD_CG_SUPPORT_GFX_CP_LS | AMD_CG_SUPPORT_GFX_3D_CGCG | AMD_CG_SUPPORT_GFX_3D_CGLS | AMD_CG_SUPPORT_GFX_CGCG | AMD_CG_SUPPORT_GFX_CGLS | AMD_CG_SUPPORT_BIF_MGCG | AMD_CG_SUPPORT_BIF_LS | AMD_CG_SUPPORT_HDP_MGCG | AMD_CG_SUPPORT_HDP_LS | AMD_CG_SUPPORT_DRM_MGCG | AMD_CG_SUPPORT_DRM_LS | AMD_CG_SUPPORT_ROM_MGCG | AMD_CG_SUPPORT_MC_MGCG | AMD_CG_SUPPORT_MC_LS | AMD_CG_SUPPORT_SDMA_MGCG | AMD_CG_SUPPORT_SDMA_LS | AMD_CG_SUPPORT_VCN_MGCG; adev->pg_flags = AMD_PG_SUPPORT_SDMA | AMD_PG_SUPPORT_VCN; } break; case CHIP_ARCTURUS: adev->asic_funcs = &vega20_asic_funcs; adev->cg_flags = AMD_CG_SUPPORT_GFX_MGCG | AMD_CG_SUPPORT_GFX_MGLS | AMD_CG_SUPPORT_GFX_CGCG | AMD_CG_SUPPORT_GFX_CGLS | AMD_CG_SUPPORT_GFX_CP_LS | AMD_CG_SUPPORT_HDP_MGCG | AMD_CG_SUPPORT_HDP_LS | AMD_CG_SUPPORT_SDMA_MGCG | AMD_CG_SUPPORT_SDMA_LS | AMD_CG_SUPPORT_MC_MGCG | AMD_CG_SUPPORT_MC_LS; adev->pg_flags = 0; adev->external_rev_id = adev->rev_id + 0x32; break; case CHIP_RENOIR: adev->asic_funcs = &soc15_asic_funcs; adev->cg_flags = AMD_CG_SUPPORT_GFX_MGCG | AMD_CG_SUPPORT_GFX_MGLS | AMD_CG_SUPPORT_GFX_3D_CGCG | AMD_CG_SUPPORT_GFX_3D_CGLS | AMD_CG_SUPPORT_GFX_CGCG | AMD_CG_SUPPORT_GFX_CGLS | AMD_CG_SUPPORT_GFX_CP_LS | AMD_CG_SUPPORT_MC_MGCG | AMD_CG_SUPPORT_MC_LS | AMD_CG_SUPPORT_SDMA_MGCG | AMD_CG_SUPPORT_SDMA_LS | AMD_CG_SUPPORT_BIF_LS | AMD_CG_SUPPORT_HDP_LS | AMD_CG_SUPPORT_ROM_MGCG | AMD_CG_SUPPORT_VCN_MGCG | AMD_CG_SUPPORT_IH_CG | AMD_CG_SUPPORT_ATHUB_LS | AMD_CG_SUPPORT_ATHUB_MGCG | AMD_CG_SUPPORT_DF_MGCG; adev->pg_flags = AMD_PG_SUPPORT_SDMA | AMD_PG_SUPPORT_VCN | AMD_PG_SUPPORT_VCN_DPG; adev->external_rev_id = adev->rev_id + 0x91; if (adev->pm.pp_feature & PP_GFXOFF_MASK) adev->pg_flags |= AMD_PG_SUPPORT_GFX_PG | AMD_PG_SUPPORT_CP | AMD_PG_SUPPORT_RLC_SMU_HS; break; default: /* FIXME: not supported yet */ return -EINVAL; } if (amdgpu_sriov_vf(adev)) { amdgpu_virt_init_setting(adev); xgpu_ai_mailbox_set_irq_funcs(adev); } return 0; } static int soc15_common_late_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; if (amdgpu_sriov_vf(adev)) xgpu_ai_mailbox_get_irq(adev); return 0; } static int soc15_common_sw_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; if (amdgpu_sriov_vf(adev)) xgpu_ai_mailbox_add_irq_id(adev); adev->df_funcs->sw_init(adev); return 0; } static int soc15_common_sw_fini(void *handle) { return 0; } static void soc15_doorbell_range_init(struct amdgpu_device *adev) { int i; struct amdgpu_ring *ring; /* sdma/ih doorbell range are programed by hypervisor */ if (!amdgpu_sriov_vf(adev)) { for (i = 0; i < adev->sdma.num_instances; i++) { ring = &adev->sdma.instance[i].ring; adev->nbio_funcs->sdma_doorbell_range(adev, i, ring->use_doorbell, ring->doorbell_index, adev->doorbell_index.sdma_doorbell_range); } adev->nbio_funcs->ih_doorbell_range(adev, adev->irq.ih.use_doorbell, adev->irq.ih.doorbell_index); } } static int soc15_common_hw_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; /* enable pcie gen2/3 link */ soc15_pcie_gen3_enable(adev); /* enable aspm */ soc15_program_aspm(adev); /* setup nbio registers */ adev->nbio_funcs->init_registers(adev); /* remap HDP registers to a hole in mmio space, * for the purpose of expose those registers * to process space */ if (adev->nbio_funcs->remap_hdp_registers) adev->nbio_funcs->remap_hdp_registers(adev); /* enable the doorbell aperture */ soc15_enable_doorbell_aperture(adev, true); /* HW doorbell routing policy: doorbell writing not * in SDMA/IH/MM/ACV range will be routed to CP. So * we need to init SDMA/IH/MM/ACV doorbell range prior * to CP ip block init and ring test. */ soc15_doorbell_range_init(adev); return 0; } static int soc15_common_hw_fini(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; /* disable the doorbell aperture */ soc15_enable_doorbell_aperture(adev, false); if (amdgpu_sriov_vf(adev)) xgpu_ai_mailbox_put_irq(adev); return 0; } static int soc15_common_suspend(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; return soc15_common_hw_fini(adev); } static int soc15_common_resume(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; return soc15_common_hw_init(adev); } static bool soc15_common_is_idle(void *handle) { return true; } static int soc15_common_wait_for_idle(void *handle) { return 0; } static int soc15_common_soft_reset(void *handle) { return 0; } static void soc15_update_hdp_light_sleep(struct amdgpu_device *adev, bool enable) { uint32_t def, data; if (adev->asic_type == CHIP_VEGA20 || adev->asic_type == CHIP_ARCTURUS) { def = data = RREG32(SOC15_REG_OFFSET(HDP, 0, mmHDP_MEM_POWER_CTRL)); if (enable && (adev->cg_flags & AMD_CG_SUPPORT_HDP_LS)) data |= HDP_MEM_POWER_CTRL__IPH_MEM_POWER_CTRL_EN_MASK | HDP_MEM_POWER_CTRL__IPH_MEM_POWER_LS_EN_MASK | HDP_MEM_POWER_CTRL__RC_MEM_POWER_CTRL_EN_MASK | HDP_MEM_POWER_CTRL__RC_MEM_POWER_LS_EN_MASK; else data &= ~(HDP_MEM_POWER_CTRL__IPH_MEM_POWER_CTRL_EN_MASK | HDP_MEM_POWER_CTRL__IPH_MEM_POWER_LS_EN_MASK | HDP_MEM_POWER_CTRL__RC_MEM_POWER_CTRL_EN_MASK | HDP_MEM_POWER_CTRL__RC_MEM_POWER_LS_EN_MASK); if (def != data) WREG32(SOC15_REG_OFFSET(HDP, 0, mmHDP_MEM_POWER_CTRL), data); } else { def = data = RREG32(SOC15_REG_OFFSET(HDP, 0, mmHDP_MEM_POWER_LS)); if (enable && (adev->cg_flags & AMD_CG_SUPPORT_HDP_LS)) data |= HDP_MEM_POWER_LS__LS_ENABLE_MASK; else data &= ~HDP_MEM_POWER_LS__LS_ENABLE_MASK; if (def != data) WREG32(SOC15_REG_OFFSET(HDP, 0, mmHDP_MEM_POWER_LS), data); } } static void soc15_update_drm_clock_gating(struct amdgpu_device *adev, bool enable) { uint32_t def, data; def = data = RREG32(SOC15_REG_OFFSET(MP0, 0, mmMP0_MISC_CGTT_CTRL0)); if (enable && (adev->cg_flags & AMD_CG_SUPPORT_DRM_MGCG)) data &= ~(0x01000000 | 0x02000000 | 0x04000000 | 0x08000000 | 0x10000000 | 0x20000000 | 0x40000000 | 0x80000000); else data |= (0x01000000 | 0x02000000 | 0x04000000 | 0x08000000 | 0x10000000 | 0x20000000 | 0x40000000 | 0x80000000); if (def != data) WREG32(SOC15_REG_OFFSET(MP0, 0, mmMP0_MISC_CGTT_CTRL0), data); } static void soc15_update_drm_light_sleep(struct amdgpu_device *adev, bool enable) { uint32_t def, data; def = data = RREG32(SOC15_REG_OFFSET(MP0, 0, mmMP0_MISC_LIGHT_SLEEP_CTRL)); if (enable && (adev->cg_flags & AMD_CG_SUPPORT_DRM_LS)) data |= 1; else data &= ~1; if (def != data) WREG32(SOC15_REG_OFFSET(MP0, 0, mmMP0_MISC_LIGHT_SLEEP_CTRL), data); } static void soc15_update_rom_medium_grain_clock_gating(struct amdgpu_device *adev, bool enable) { uint32_t def, data; def = data = RREG32(SOC15_REG_OFFSET(SMUIO, 0, mmCGTT_ROM_CLK_CTRL0)); if (enable && (adev->cg_flags & AMD_CG_SUPPORT_ROM_MGCG)) data &= ~(CGTT_ROM_CLK_CTRL0__SOFT_OVERRIDE0_MASK | CGTT_ROM_CLK_CTRL0__SOFT_OVERRIDE1_MASK); else data |= CGTT_ROM_CLK_CTRL0__SOFT_OVERRIDE0_MASK | CGTT_ROM_CLK_CTRL0__SOFT_OVERRIDE1_MASK; if (def != data) WREG32(SOC15_REG_OFFSET(SMUIO, 0, mmCGTT_ROM_CLK_CTRL0), data); } static int soc15_common_set_clockgating_state(void *handle, enum amd_clockgating_state state) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; if (amdgpu_sriov_vf(adev)) return 0; switch (adev->asic_type) { case CHIP_VEGA10: case CHIP_VEGA12: case CHIP_VEGA20: adev->nbio_funcs->update_medium_grain_clock_gating(adev, state == AMD_CG_STATE_GATE ? true : false); adev->nbio_funcs->update_medium_grain_light_sleep(adev, state == AMD_CG_STATE_GATE ? true : false); soc15_update_hdp_light_sleep(adev, state == AMD_CG_STATE_GATE ? true : false); soc15_update_drm_clock_gating(adev, state == AMD_CG_STATE_GATE ? true : false); soc15_update_drm_light_sleep(adev, state == AMD_CG_STATE_GATE ? true : false); soc15_update_rom_medium_grain_clock_gating(adev, state == AMD_CG_STATE_GATE ? true : false); adev->df_funcs->update_medium_grain_clock_gating(adev, state == AMD_CG_STATE_GATE ? true : false); break; case CHIP_RAVEN: case CHIP_RENOIR: adev->nbio_funcs->update_medium_grain_clock_gating(adev, state == AMD_CG_STATE_GATE ? true : false); adev->nbio_funcs->update_medium_grain_light_sleep(adev, state == AMD_CG_STATE_GATE ? true : false); soc15_update_hdp_light_sleep(adev, state == AMD_CG_STATE_GATE ? true : false); soc15_update_drm_clock_gating(adev, state == AMD_CG_STATE_GATE ? true : false); soc15_update_drm_light_sleep(adev, state == AMD_CG_STATE_GATE ? true : false); soc15_update_rom_medium_grain_clock_gating(adev, state == AMD_CG_STATE_GATE ? true : false); break; case CHIP_ARCTURUS: soc15_update_hdp_light_sleep(adev, state == AMD_CG_STATE_GATE ? true : false); break; default: break; } return 0; } static void soc15_common_get_clockgating_state(void *handle, u32 *flags) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; int data; if (amdgpu_sriov_vf(adev)) *flags = 0; adev->nbio_funcs->get_clockgating_state(adev, flags); /* AMD_CG_SUPPORT_HDP_LS */ data = RREG32(SOC15_REG_OFFSET(HDP, 0, mmHDP_MEM_POWER_LS)); if (data & HDP_MEM_POWER_LS__LS_ENABLE_MASK) *flags |= AMD_CG_SUPPORT_HDP_LS; /* AMD_CG_SUPPORT_DRM_MGCG */ data = RREG32(SOC15_REG_OFFSET(MP0, 0, mmMP0_MISC_CGTT_CTRL0)); if (!(data & 0x01000000)) *flags |= AMD_CG_SUPPORT_DRM_MGCG; /* AMD_CG_SUPPORT_DRM_LS */ data = RREG32(SOC15_REG_OFFSET(MP0, 0, mmMP0_MISC_LIGHT_SLEEP_CTRL)); if (data & 0x1) *flags |= AMD_CG_SUPPORT_DRM_LS; /* AMD_CG_SUPPORT_ROM_MGCG */ data = RREG32(SOC15_REG_OFFSET(SMUIO, 0, mmCGTT_ROM_CLK_CTRL0)); if (!(data & CGTT_ROM_CLK_CTRL0__SOFT_OVERRIDE0_MASK)) *flags |= AMD_CG_SUPPORT_ROM_MGCG; adev->df_funcs->get_clockgating_state(adev, flags); } static int soc15_common_set_powergating_state(void *handle, enum amd_powergating_state state) { /* todo */ return 0; } const struct amd_ip_funcs soc15_common_ip_funcs = { .name = "soc15_common", .early_init = soc15_common_early_init, .late_init = soc15_common_late_init, .sw_init = soc15_common_sw_init, .sw_fini = soc15_common_sw_fini, .hw_init = soc15_common_hw_init, .hw_fini = soc15_common_hw_fini, .suspend = soc15_common_suspend, .resume = soc15_common_resume, .is_idle = soc15_common_is_idle, .wait_for_idle = soc15_common_wait_for_idle, .soft_reset = soc15_common_soft_reset, .set_clockgating_state = soc15_common_set_clockgating_state, .set_powergating_state = soc15_common_set_powergating_state, .get_clockgating_state= soc15_common_get_clockgating_state, };
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
You can’t perform that action at this time.