/*
* Copyright 2021 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 "amdgpu.h"
#include "hdp_v5_2.h"
#include "hdp/hdp_5_2_1_offset.h"
#include "hdp/hdp_5_2_1_sh_mask.h"
#include <uapi/linux/kfd_ioctl.h>
static void hdp_v5_2_flush_hdp(struct amdgpu_device *adev,
struct amdgpu_ring *ring)
{
if (!ring || !ring->funcs->emit_wreg) {
WREG32_NO_KIQ((adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2 ,
0 );
if (amdgpu_sriov_vf(adev)) {
/* this is fine because SR_IOV doesn't remap the register */
RREG32_NO_KIQ((adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2 );
} else {
/* We just need to read back a register to post the write.
* Reading back the remapped register causes problems on
* some platforms so just read back the memory size register .
*/
if (adev->nbio.funcs->get_memsize)
adev->nbio.funcs->get_memsize(adev);
}
} else {
amdgpu_ring_emit_wreg(ring,
(adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2 ,
0 );
}
}
static void hdp_v5_2_update_mem_power_gating(struct amdgpu_device *adev,
bool enable)
{
uint32_t hdp_clk_cntl;
uint32_t hdp_mem_pwr_cntl;
if (!(adev->cg_flags & (AMD_CG_SUPPORT_HDP_LS |
AMD_CG_SUPPORT_HDP_DS |
AMD_CG_SUPPORT_HDP_SD)))
return ;
hdp_clk_cntl = RREG32_SOC15(HDP, 0 , regHDP_CLK_CNTL);
hdp_mem_pwr_cntl = RREG32_SOC15(HDP, 0 , regHDP_MEM_POWER_CTRL);
/* Before doing clock/power mode switch, forced on MEM clock */
hdp_clk_cntl = REG_SET_FIELD(hdp_clk_cntl, HDP_CLK_CNTL,
ATOMIC_MEM_CLK_SOFT_OVERRIDE, 1 );
hdp_clk_cntl = REG_SET_FIELD(hdp_clk_cntl, HDP_CLK_CNTL,
RC_MEM_CLK_SOFT_OVERRIDE, 1 );
WREG32_SOC15(HDP, 0 , regHDP_CLK_CNTL, hdp_clk_cntl);
/* disable clock and power gating before any changing */
hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL,
ATOMIC_MEM_POWER_CTRL_EN, 0 );
hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL,
ATOMIC_MEM_POWER_LS_EN, 0 );
hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL,
ATOMIC_MEM_POWER_DS_EN, 0 );
hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL,
ATOMIC_MEM_POWER_SD_EN, 0 );
hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL,
RC_MEM_POWER_CTRL_EN, 0 );
hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL,
RC_MEM_POWER_LS_EN, 0 );
hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL,
RC_MEM_POWER_DS_EN, 0 );
hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL,
RC_MEM_POWER_SD_EN, 0 );
WREG32_SOC15(HDP, 0 , regHDP_MEM_POWER_CTRL, hdp_mem_pwr_cntl);
/* Already disabled above. The actions below are for "enabled" only */
if (enable) {
/* only one clock gating mode (LS/DS/SD) can be enabled */
if (adev->cg_flags & AMD_CG_SUPPORT_HDP_SD) {
hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl,
HDP_MEM_POWER_CTRL,
ATOMIC_MEM_POWER_SD_EN, 1 );
hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl,
HDP_MEM_POWER_CTRL,
RC_MEM_POWER_SD_EN, 1 );
} else if (adev->cg_flags & AMD_CG_SUPPORT_HDP_LS) {
hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl,
HDP_MEM_POWER_CTRL,
ATOMIC_MEM_POWER_LS_EN, 1 );
hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl,
HDP_MEM_POWER_CTRL,
RC_MEM_POWER_LS_EN, 1 );
} else if (adev->cg_flags & AMD_CG_SUPPORT_HDP_DS) {
hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl,
HDP_MEM_POWER_CTRL,
ATOMIC_MEM_POWER_DS_EN, 1 );
hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl,
HDP_MEM_POWER_CTRL,
RC_MEM_POWER_DS_EN, 1 );
}
/* confirmed that ATOMIC/RC_MEM_POWER_CTRL_EN have to be set for SRAM LS/DS/SD */
if (adev->cg_flags & (AMD_CG_SUPPORT_HDP_LS | AMD_CG_SUPPORT_HDP_DS |
AMD_CG_SUPPORT_HDP_SD)) {
hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL,
ATOMIC_MEM_POWER_CTRL_EN, 1 );
hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL,
RC_MEM_POWER_CTRL_EN, 1 );
WREG32_SOC15(HDP, 0 , regHDP_MEM_POWER_CTRL, hdp_mem_pwr_cntl);
}
}
/* disable MEM clock override after clock/power mode changing */
hdp_clk_cntl = REG_SET_FIELD(hdp_clk_cntl, HDP_CLK_CNTL,
ATOMIC_MEM_CLK_SOFT_OVERRIDE, 0 );
hdp_clk_cntl = REG_SET_FIELD(hdp_clk_cntl, HDP_CLK_CNTL,
RC_MEM_CLK_SOFT_OVERRIDE, 0 );
WREG32_SOC15(HDP, 0 , regHDP_CLK_CNTL, hdp_clk_cntl);
}
static void hdp_v5_2_update_medium_grain_clock_gating(struct amdgpu_device *adev,
bool enable)
{
uint32_t hdp_clk_cntl;
if (!(adev->cg_flags & AMD_CG_SUPPORT_HDP_MGCG))
return ;
hdp_clk_cntl = RREG32_SOC15(HDP, 0 , regHDP_CLK_CNTL);
if (enable) {
hdp_clk_cntl &=
~(uint32_t)
(HDP_CLK_CNTL__ATOMIC_MEM_CLK_SOFT_OVERRIDE_MASK |
HDP_CLK_CNTL__RC_MEM_CLK_SOFT_OVERRIDE_MASK |
HDP_CLK_CNTL__DBUS_CLK_SOFT_OVERRIDE_MASK |
HDP_CLK_CNTL__DYN_CLK_SOFT_OVERRIDE_MASK |
HDP_CLK_CNTL__XDP_REG_CLK_SOFT_OVERRIDE_MASK |
HDP_CLK_CNTL__HDP_REG_CLK_SOFT_OVERRIDE_MASK);
} else {
hdp_clk_cntl |= HDP_CLK_CNTL__ATOMIC_MEM_CLK_SOFT_OVERRIDE_MASK |
HDP_CLK_CNTL__RC_MEM_CLK_SOFT_OVERRIDE_MASK |
HDP_CLK_CNTL__DBUS_CLK_SOFT_OVERRIDE_MASK |
HDP_CLK_CNTL__DYN_CLK_SOFT_OVERRIDE_MASK |
HDP_CLK_CNTL__XDP_REG_CLK_SOFT_OVERRIDE_MASK |
HDP_CLK_CNTL__HDP_REG_CLK_SOFT_OVERRIDE_MASK;
}
WREG32_SOC15(HDP, 0 , regHDP_CLK_CNTL, hdp_clk_cntl);
}
static void hdp_v5_2_get_clockgating_state(struct amdgpu_device *adev,
u64 *flags)
{
uint32_t tmp;
/* AMD_CG_SUPPORT_HDP_MGCG */
tmp = RREG32_SOC15(HDP, 0 , regHDP_CLK_CNTL);
if (!(tmp & (HDP_CLK_CNTL__ATOMIC_MEM_CLK_SOFT_OVERRIDE_MASK |
HDP_CLK_CNTL__RC_MEM_CLK_SOFT_OVERRIDE_MASK |
HDP_CLK_CNTL__DBUS_CLK_SOFT_OVERRIDE_MASK |
HDP_CLK_CNTL__DYN_CLK_SOFT_OVERRIDE_MASK |
HDP_CLK_CNTL__XDP_REG_CLK_SOFT_OVERRIDE_MASK |
HDP_CLK_CNTL__HDP_REG_CLK_SOFT_OVERRIDE_MASK)))
*flags |= AMD_CG_SUPPORT_HDP_MGCG;
/* AMD_CG_SUPPORT_HDP_LS/DS/SD */
tmp = RREG32_SOC15(HDP, 0 , regHDP_MEM_POWER_CTRL);
if (tmp & HDP_MEM_POWER_CTRL__ATOMIC_MEM_POWER_LS_EN_MASK)
*flags |= AMD_CG_SUPPORT_HDP_LS;
else if (tmp & HDP_MEM_POWER_CTRL__ATOMIC_MEM_POWER_DS_EN_MASK)
*flags |= AMD_CG_SUPPORT_HDP_DS;
else if (tmp & HDP_MEM_POWER_CTRL__ATOMIC_MEM_POWER_SD_EN_MASK)
*flags |= AMD_CG_SUPPORT_HDP_SD;
}
static void hdp_v5_2_update_clock_gating(struct amdgpu_device *adev,
bool enable)
{
hdp_v5_2_update_mem_power_gating(adev, enable);
hdp_v5_2_update_medium_grain_clock_gating(adev, enable);
}
const struct amdgpu_hdp_funcs hdp_v5_2_funcs = {
.flush_hdp = hdp_v5_2_flush_hdp,
.update_clock_gating = hdp_v5_2_update_clock_gating,
.get_clock_gating_state = hdp_v5_2_get_clockgating_state,
};
Messung V0.5 in Prozent C=95 H=100 G=97
¤ Dauer der Verarbeitung: 0.11 Sekunden
(vorverarbeitet am 2026-10-02)
¤
*© Formatika GbR, Deutschland