Merge tag 'amd-drm-next-5.10-2020-09-03' of git://people.freedesktop.org/~agd5f/linux into drm-next

amd-drm-next-5.10-2020-09-03:

amdgpu:
- RAS fixes
- Sienna Cichlid updates
- Navy Flounder updates
- DCE6 (SI) support in DC
- Enable plane rotation
- Rework pre-OS vram reservation handling during driver init
- Add standard interface to dump GPU metrics table from SMU
- Rework tiling and tmz state handling in atomic commits
- Pstate fixes
- Add voltage and power hwmon interfaces for renoir
- SW CTF fixes
- S/G display fix for Raven
- Print client strings for vmfaults for vega and newer
- Manual fan control fixes
- Display updates
- Reorg power management directory structure
- Misc bug fixes
- Misc code cleanups

amdkfd:
- Topology fixes
- Add SMI events for thermal throttling and GPU resets

radeon:
- switch from pci_* to dma_* for dma allocations
- PLL fix

Scheduler:
- Clean up priority levels

UAPI:
- amdgpu INFO IOCTL query update for TMZ state
  https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6049
- amdkfd SMI event interface updates
  https://github.com/RadeonOpenCompute/rocm_smi_lib/tree/therm_thrott

From: Alex Deucher <alexdeucher@gmail.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200903222921.4152-1-alexander.deucher@amd.com
This commit is contained in:
Dave Airlie
2020-09-08 16:40:13 +10:00
455 changed files with 14098 additions and 3210 deletions

View File

@@ -0,0 +1,39 @@
#
# Copyright 2020 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.
#
AMD_PP_PATH = ../pm/powerplay
PP_LIBS = smumgr hwmgr
AMD_POWERPLAY = $(addsuffix /Makefile,$(addprefix $(FULL_AMD_PATH)/pm/powerplay/,$(PP_LIBS)))
include $(AMD_POWERPLAY)
POWER_MGR-y = amd_powerplay.o
POWER_MGR-$(CONFIG_DRM_AMDGPU_CIK)+= kv_dpm.o kv_smc.o
POWER_MGR-$(CONFIG_DRM_AMDGPU_SI)+= si_dpm.o si_smc.o
AMD_PP_POWER = $(addprefix $(AMD_PP_PATH)/,$(POWER_MGR-y))
AMD_POWERPLAY_FILES += $(AMD_PP_POWER)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,29 @@
/*
* Copyright 2014 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.
*
*/
#ifndef __CIK_DPM_H__
#define __CIK_DPM_H__
extern const struct amdgpu_ip_block_version kv_smu_ip_block;
#endif

View File

@@ -0,0 +1,44 @@
#
# Copyright 2017 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.
#
#
# Makefile for the 'hw manager' sub-component of powerplay.
# It provides the hardware management services for the driver.
HARDWARE_MGR = hwmgr.o processpptables.o \
hardwaremanager.o smu8_hwmgr.o \
pppcielanes.o\
process_pptables_v1_0.o ppatomctrl.o ppatomfwctrl.o \
smu7_hwmgr.o smu7_powertune.o smu7_thermal.o \
smu7_clockpowergating.o \
vega10_processpptables.o vega10_hwmgr.o vega10_powertune.o \
vega10_thermal.o smu10_hwmgr.o pp_psm.o\
vega12_processpptables.o vega12_hwmgr.o \
vega12_thermal.o \
pp_overdriver.o smu_helper.o \
vega20_processpptables.o vega20_hwmgr.o vega20_powertune.o \
vega20_thermal.o common_baco.o vega10_baco.o vega20_baco.o \
vega12_baco.o smu9_baco.o tonga_baco.o polaris_baco.o fiji_baco.o \
ci_baco.o smu7_baco.o
AMD_PP_HWMGR = $(addprefix $(AMD_PP_PATH)/hwmgr/,$(HARDWARE_MGR))
AMD_POWERPLAY_FILES += $(AMD_PP_HWMGR)

View File

@@ -0,0 +1,195 @@
/*
* Copyright 2019 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 "ci_baco.h"
#include "gmc/gmc_7_1_d.h"
#include "gmc/gmc_7_1_sh_mask.h"
#include "bif/bif_4_1_d.h"
#include "bif/bif_4_1_sh_mask.h"
#include "dce/dce_8_0_d.h"
#include "dce/dce_8_0_sh_mask.h"
#include "smu/smu_7_0_1_d.h"
#include "smu/smu_7_0_1_sh_mask.h"
#include "gca/gfx_7_2_d.h"
#include "gca/gfx_7_2_sh_mask.h"
static const struct baco_cmd_entry gpio_tbl[] =
{
{ CMD_WRITE, mmGPIOPAD_EN, 0, 0, 0, 0x0 },
{ CMD_WRITE, mmGPIOPAD_PD_EN, 0, 0, 0, 0x0 },
{ CMD_WRITE, mmGPIOPAD_PU_EN, 0, 0, 0, 0x0 },
{ CMD_WRITE, mmGPIOPAD_MASK, 0, 0, 0, 0xff77ffff },
{ CMD_WRITE, mmDC_GPIO_DVODATA_EN, 0, 0, 0, 0x0 },
{ CMD_WRITE, mmDC_GPIO_DVODATA_MASK, 0, 0, 0, 0xffffffff },
{ CMD_WRITE, mmDC_GPIO_GENERIC_EN, 0, 0, 0, 0x0 },
{ CMD_READMODIFYWRITE, mmDC_GPIO_GENERIC_MASK, 0, 0, 0, 0x03333333 },
{ CMD_WRITE, mmDC_GPIO_SYNCA_EN, 0, 0, 0, 0x0 },
{ CMD_READMODIFYWRITE, mmDC_GPIO_SYNCA_MASK, 0, 0, 0, 0x00001111 }
};
static const struct baco_cmd_entry enable_fb_req_rej_tbl[] =
{
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC0300024 },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x1, 0x0, 0, 0x1 },
{ CMD_WRITE, mmBIF_FB_EN, 0, 0, 0, 0x0 }
};
static const struct baco_cmd_entry use_bclk_tbl[] =
{
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL__SPLL_BYPASS_EN_MASK, CG_SPLL_FUNC_CNTL__SPLL_BYPASS_EN__SHIFT, 0, 0x1 },
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL_2 },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL_2__SPLL_BYPASS_CHG_MASK, CG_SPLL_FUNC_CNTL_2__SPLL_BYPASS_CHG__SHIFT, 0, 0x1 },
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_STATUS },
{ CMD_WAITFOR, mmGCK_SMC_IND_DATA, CG_SPLL_STATUS__SPLL_CHG_STATUS_MASK, 0, 0xffffffff, 0x2 },
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL_2 },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL_2__SPLL_BYPASS_CHG_MASK, CG_SPLL_FUNC_CNTL_2__SPLL_BYPASS_CHG__SHIFT, 0, 0x0 },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL_2__SPLL_CTLREQ_CHG_MASK, CG_SPLL_FUNC_CNTL_2__SPLL_CTLREQ_CHG__SHIFT, 0, 0x1 },
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_STATUS },
{ CMD_WAITFOR, mmGCK_SMC_IND_DATA, CG_SPLL_STATUS__SPLL_CHG_STATUS_MASK, 0, 0xffffffff, 0x2 },
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL_2 },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL_2__SPLL_CTLREQ_CHG_MASK, CG_SPLL_FUNC_CNTL_2__SPLL_CTLREQ_CHG__SHIFT, 0, 0x0 },
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC0500170 },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x4000000, 0x1a, 0, 0x1 },
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixMPLL_BYPASSCLK_SEL },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL_MASK, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL__SHIFT, 0, 0x2 },
{ CMD_READMODIFYWRITE, mmMPLL_CNTL_MODE, MPLL_CNTL_MODE__MPLL_SW_DIR_CONTROL_MASK, MPLL_CNTL_MODE__MPLL_SW_DIR_CONTROL__SHIFT, 0, 0x1 },
{ CMD_READMODIFYWRITE, mmMPLL_CNTL_MODE, MPLL_CNTL_MODE__MPLL_MCLK_SEL_MASK, MPLL_CNTL_MODE__MPLL_MCLK_SEL__SHIFT, 0, 0x0 }
};
static const struct baco_cmd_entry turn_off_plls_tbl[] =
{
{ CMD_READMODIFYWRITE, mmDISPPLL_BG_CNTL, DISPPLL_BG_CNTL__DISPPLL_BG_PDN_MASK, DISPPLL_BG_CNTL__DISPPLL_BG_PDN__SHIFT, 0, 0x1 },
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_CLKPIN_CNTL_DC },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_CLKPIN_CNTL_DC__OSC_EN_MASK, CG_CLKPIN_CNTL_DC__OSC_EN__SHIFT, 0, 0x0 },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_CLKPIN_CNTL_DC__XTALIN_SEL_MASK, CG_CLKPIN_CNTL_DC__XTALIN_SEL__SHIFT, 0, 0x0 },
{ CMD_READMODIFYWRITE, mmPLL_CNTL, PLL_CNTL__PLL_RESET_MASK, PLL_CNTL__PLL_RESET__SHIFT, 0, 0x1 },
{ CMD_READMODIFYWRITE, mmPLL_CNTL, PLL_CNTL__PLL_POWER_DOWN_MASK, PLL_CNTL__PLL_POWER_DOWN__SHIFT, 0, 0x1 },
{ CMD_READMODIFYWRITE, mmPLL_CNTL, PLL_CNTL__PLL_BYPASS_CAL_MASK, PLL_CNTL__PLL_BYPASS_CAL__SHIFT, 0, 0x1 },
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL__SPLL_RESET_MASK, CG_SPLL_FUNC_CNTL__SPLL_RESET__SHIFT, 0, 0x1 },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL__SPLL_PWRON_MASK, CG_SPLL_FUNC_CNTL__SPLL_PWRON__SHIFT, 0, 0x0 },
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC0500170 },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x2000000, 0x19, 0, 0x1 },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x8000000, 0x1b, 0, 0x0 },
{ CMD_READMODIFYWRITE, mmMPLL_CNTL_MODE, MPLL_CNTL_MODE__GLOBAL_MPLL_RESET_MASK, MPLL_CNTL_MODE__GLOBAL_MPLL_RESET__SHIFT, 0, 0x1 },
{ CMD_WRITE, mmMPLL_CONTROL, 0, 0, 0, 0x00000006 },
{ CMD_WRITE, mmMC_IO_RXCNTL_DPHY0_D0, 0, 0, 0, 0x00007740 },
{ CMD_WRITE, mmMC_IO_RXCNTL_DPHY0_D1, 0, 0, 0, 0x00007740 },
{ CMD_WRITE, mmMC_IO_RXCNTL_DPHY1_D0, 0, 0, 0, 0x00007740 },
{ CMD_WRITE, mmMC_IO_RXCNTL_DPHY1_D1, 0, 0, 0, 0x00007740 },
{ CMD_READMODIFYWRITE, mmMCLK_PWRMGT_CNTL, MCLK_PWRMGT_CNTL__MRDCK0_PDNB_MASK, MCLK_PWRMGT_CNTL__MRDCK0_PDNB__SHIFT, 0, 0x0 },
{ CMD_READMODIFYWRITE, mmMCLK_PWRMGT_CNTL, MCLK_PWRMGT_CNTL__MRDCK1_PDNB_MASK, MCLK_PWRMGT_CNTL__MRDCK1_PDNB__SHIFT, 0, 0x0 },
{ CMD_READMODIFYWRITE, mmMC_SEQ_CNTL_2, MC_SEQ_CNTL_2__DRST_PU_MASK, MC_SEQ_CNTL_2__DRST_PU__SHIFT, 0, 0x0 },
{ CMD_READMODIFYWRITE, mmMC_SEQ_CNTL_2, MC_SEQ_CNTL_2__DRST_PD_MASK, MC_SEQ_CNTL_2__DRST_PD__SHIFT, 0, 0x0 },
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_CLKPIN_CNTL_2 },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_CLKPIN_CNTL_2__FORCE_BIF_REFCLK_EN_MASK, CG_CLKPIN_CNTL_2__FORCE_BIF_REFCLK_EN__SHIFT, 0, 0x0 },
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixMPLL_BYPASSCLK_SEL },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL_MASK, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL__SHIFT, 0, 0x4 },
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixMISC_CLK_CTRL },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MISC_CLK_CTRL__DEEP_SLEEP_CLK_SEL_MASK, MISC_CLK_CTRL__DEEP_SLEEP_CLK_SEL__SHIFT, 0, 0x2 },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MISC_CLK_CTRL__ZCLK_SEL_MASK, MISC_CLK_CTRL__ZCLK_SEL__SHIFT, 0, 0x2 },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MISC_CLK_CTRL__DFT_SMS_PG_CLK_SEL_MASK, MISC_CLK_CTRL__DFT_SMS_PG_CLK_SEL__SHIFT, 0, 0x2 },
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixTHM_CLK_CNTL },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, THM_CLK_CNTL__CMON_CLK_SEL_MASK, THM_CLK_CNTL__CMON_CLK_SEL__SHIFT, 0, 0x2 },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, THM_CLK_CNTL__TMON_CLK_SEL_MASK, THM_CLK_CNTL__TMON_CLK_SEL__SHIFT, 0, 0x2 }
};
static const struct baco_cmd_entry enter_baco_tbl[] =
{
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_EN_MASK, BACO_CNTL__BACO_EN__SHIFT, 0, 0x01 },
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BCLK_OFF_MASK, BACO_CNTL__BACO_BCLK_OFF__SHIFT, 0, 0x01 },
{ CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_BCLK_OFF_MASK, 0, 5, 0x02 },
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ISO_DIS_MASK, BACO_CNTL__BACO_ISO_DIS__SHIFT, 0, 0x00 },
{ CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_ISO_DIS_MASK, 0, 5, 0x00 },
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ANA_ISO_DIS_MASK, BACO_CNTL__BACO_ANA_ISO_DIS__SHIFT, 0, 0x00 },
{ CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_ANA_ISO_DIS_MASK, 0, 5, 0x00 },
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, BACO_CNTL__BACO_POWER_OFF__SHIFT, 0, 0x01 },
{ CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, 0, 5, 0x08 },
{ CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_MODE_MASK, 0, 0xffffffff, 0x40 }
};
#define BACO_CNTL__PWRGOOD_MASK BACO_CNTL__PWRGOOD_GPIO_MASK+BACO_CNTL__PWRGOOD_MEM_MASK+BACO_CNTL__PWRGOOD_DVO_MASK
static const struct baco_cmd_entry exit_baco_tbl[] =
{
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_RESET_EN_MASK, BACO_CNTL__BACO_RESET_EN__SHIFT, 0, 0x01 },
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BCLK_OFF_MASK, BACO_CNTL__BACO_BCLK_OFF__SHIFT, 0, 0x00 },
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, BACO_CNTL__BACO_POWER_OFF__SHIFT, 0, 0x00 },
{ CMD_DELAY_MS, 0, 0, 0, 20, 0 },
{ CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__PWRGOOD_BF_MASK, 0, 0xffffffff, 0x20 },
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ISO_DIS_MASK, BACO_CNTL__BACO_ISO_DIS__SHIFT, 0, 0x01 },
{ CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__PWRGOOD_MASK, 0, 5, 0x1c },
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ANA_ISO_DIS_MASK, BACO_CNTL__BACO_ANA_ISO_DIS__SHIFT, 0, 0x01 },
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_RESET_EN_MASK, BACO_CNTL__BACO_RESET_EN__SHIFT, 0, 0x00 },
{ CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__RCU_BIF_CONFIG_DONE_MASK, 0, 5, 0x10 },
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_EN_MASK, BACO_CNTL__BACO_EN__SHIFT, 0, 0x00 },
{ CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_MODE_MASK, 0, 0xffffffff, 0x00 }
};
static const struct baco_cmd_entry clean_baco_tbl[] =
{
{ CMD_WRITE, mmBIOS_SCRATCH_6, 0, 0, 0, 0 },
{ CMD_WRITE, mmCP_PFP_UCODE_ADDR, 0, 0, 0, 0 }
};
int ci_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state)
{
enum BACO_STATE cur_state;
smu7_baco_get_state(hwmgr, &cur_state);
if (cur_state == state)
/* aisc already in the target state */
return 0;
if (state == BACO_STATE_IN) {
baco_program_registers(hwmgr, gpio_tbl, ARRAY_SIZE(gpio_tbl));
baco_program_registers(hwmgr, enable_fb_req_rej_tbl,
ARRAY_SIZE(enable_fb_req_rej_tbl));
baco_program_registers(hwmgr, use_bclk_tbl, ARRAY_SIZE(use_bclk_tbl));
baco_program_registers(hwmgr, turn_off_plls_tbl,
ARRAY_SIZE(turn_off_plls_tbl));
if (baco_program_registers(hwmgr, enter_baco_tbl,
ARRAY_SIZE(enter_baco_tbl)))
return 0;
} else if (state == BACO_STATE_OUT) {
/* HW requires at least 20ms between regulator off and on */
msleep(20);
/* Execute Hardware BACO exit sequence */
if (baco_program_registers(hwmgr, exit_baco_tbl,
ARRAY_SIZE(exit_baco_tbl))) {
if (baco_program_registers(hwmgr, clean_baco_tbl,
ARRAY_SIZE(clean_baco_tbl)))
return 0;
}
}
return -EINVAL;
}

View File

@@ -0,0 +1,29 @@
/*
* Copyright 2019 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.
*
*/
#ifndef __CI_BACO_H__
#define __CI_BACO_H__
#include "smu7_baco.h"
extern int ci_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state);
#endif

View File

@@ -0,0 +1,120 @@
/*
* Copyright 2018 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 "common_baco.h"
static bool baco_wait_register(struct pp_hwmgr *hwmgr, u32 reg, u32 mask, u32 value)
{
struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev);
u32 timeout = 5000, data;
do {
msleep(1);
data = RREG32(reg);
timeout--;
} while (value != (data & mask) && (timeout != 0));
if (timeout == 0)
return false;
return true;
}
static bool baco_cmd_handler(struct pp_hwmgr *hwmgr, u32 command, u32 reg, u32 mask,
u32 shift, u32 value, u32 timeout)
{
struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev);
u32 data;
bool ret = true;
switch (command) {
case CMD_WRITE:
WREG32(reg, value << shift);
break;
case CMD_READMODIFYWRITE:
data = RREG32(reg);
data = (data & (~mask)) | (value << shift);
WREG32(reg, data);
break;
case CMD_WAITFOR:
ret = baco_wait_register(hwmgr, reg, mask, value);
break;
case CMD_DELAY_MS:
if (timeout)
/* Delay in milli Seconds */
msleep(timeout);
break;
case CMD_DELAY_US:
if (timeout)
/* Delay in micro Seconds */
udelay(timeout);
break;
default:
dev_warn(adev->dev, "Invalid BACO command.\n");
ret = false;
}
return ret;
}
bool baco_program_registers(struct pp_hwmgr *hwmgr,
const struct baco_cmd_entry *entry,
const u32 array_size)
{
u32 i, reg = 0;
for (i = 0; i < array_size; i++) {
if ((entry[i].cmd == CMD_WRITE) ||
(entry[i].cmd == CMD_READMODIFYWRITE) ||
(entry[i].cmd == CMD_WAITFOR))
reg = entry[i].reg_offset;
if (!baco_cmd_handler(hwmgr, entry[i].cmd, reg, entry[i].mask,
entry[i].shift, entry[i].val, entry[i].timeout))
return false;
}
return true;
}
bool soc15_baco_program_registers(struct pp_hwmgr *hwmgr,
const struct soc15_baco_cmd_entry *entry,
const u32 array_size)
{
struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev);
u32 i, reg = 0;
for (i = 0; i < array_size; i++) {
if ((entry[i].cmd == CMD_WRITE) ||
(entry[i].cmd == CMD_READMODIFYWRITE) ||
(entry[i].cmd == CMD_WAITFOR))
reg = adev->reg_offset[entry[i].hwip][entry[i].inst][entry[i].seg]
+ entry[i].reg_offset;
if (!baco_cmd_handler(hwmgr, entry[i].cmd, reg, entry[i].mask,
entry[i].shift, entry[i].val, entry[i].timeout))
return false;
}
return true;
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright 2018 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.
*
*/
#ifndef __COMMON_BOCO_H__
#define __COMMON_BOCO_H__
#include "hwmgr.h"
enum baco_cmd_type {
CMD_WRITE = 0,
CMD_READMODIFYWRITE,
CMD_WAITFOR,
CMD_DELAY_MS,
CMD_DELAY_US,
};
struct baco_cmd_entry {
enum baco_cmd_type cmd;
uint32_t reg_offset;
uint32_t mask;
uint32_t shift;
uint32_t timeout;
uint32_t val;
};
struct soc15_baco_cmd_entry {
enum baco_cmd_type cmd;
uint32_t hwip;
uint32_t inst;
uint32_t seg;
uint32_t reg_offset;
uint32_t mask;
uint32_t shift;
uint32_t timeout;
uint32_t val;
};
extern bool baco_program_registers(struct pp_hwmgr *hwmgr,
const struct baco_cmd_entry *entry,
const u32 array_size);
extern bool soc15_baco_program_registers(struct pp_hwmgr *hwmgr,
const struct soc15_baco_cmd_entry *entry,
const u32 array_size);
#endif

View File

@@ -0,0 +1,196 @@
/*
* Copyright 2019 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 "fiji_baco.h"
#include "gmc/gmc_8_1_d.h"
#include "gmc/gmc_8_1_sh_mask.h"
#include "bif/bif_5_0_d.h"
#include "bif/bif_5_0_sh_mask.h"
#include "dce/dce_10_0_d.h"
#include "dce/dce_10_0_sh_mask.h"
#include "smu/smu_7_1_3_d.h"
#include "smu/smu_7_1_3_sh_mask.h"
static const struct baco_cmd_entry gpio_tbl[] =
{
{ CMD_WRITE, mmGPIOPAD_EN, 0, 0, 0, 0x0 },
{ CMD_WRITE, mmGPIOPAD_PD_EN, 0, 0, 0, 0x0 },
{ CMD_WRITE, mmGPIOPAD_PU_EN, 0, 0, 0, 0x0 },
{ CMD_WRITE, mmGPIOPAD_MASK, 0, 0, 0, 0xff77ffff },
{ CMD_WRITE, mmDC_GPIO_DVODATA_EN, 0, 0, 0, 0x0 },
{ CMD_WRITE, mmDC_GPIO_DVODATA_MASK, 0, 0, 0, 0xffffffff },
{ CMD_WRITE, mmDC_GPIO_GENERIC_EN, 0, 0, 0, 0x0 },
{ CMD_READMODIFYWRITE, mmDC_GPIO_GENERIC_MASK, 0, 0, 0, 0x03333333 },
{ CMD_WRITE, mmDC_GPIO_SYNCA_EN, 0, 0, 0, 0x0 },
{ CMD_READMODIFYWRITE, mmDC_GPIO_SYNCA_MASK, 0, 0, 0, 0x00001111 }
};
static const struct baco_cmd_entry enable_fb_req_rej_tbl[] =
{
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC0300024 },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x1, 0x0, 0, 0x1 },
{ CMD_WRITE, mmBIF_FB_EN, 0, 0, 0, 0x0 }
};
static const struct baco_cmd_entry use_bclk_tbl[] =
{
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL__SPLL_BYPASS_EN_MASK, CG_SPLL_FUNC_CNTL__SPLL_BYPASS_EN__SHIFT, 0, 0x1 },
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL_2 },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL_2__SPLL_BYPASS_CHG_MASK, CG_SPLL_FUNC_CNTL_2__SPLL_BYPASS_CHG__SHIFT, 0, 0x1 },
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_STATUS },
{ CMD_WAITFOR, mmGCK_SMC_IND_DATA, CG_SPLL_STATUS__SPLL_CHG_STATUS_MASK, 0, 0xffffffff, 0x2 },
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL_2 },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL_2__SPLL_BYPASS_CHG_MASK, CG_SPLL_FUNC_CNTL_2__SPLL_BYPASS_CHG__SHIFT, 0, 0x0 },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL_2__SPLL_CTLREQ_CHG_MASK, CG_SPLL_FUNC_CNTL_2__SPLL_CTLREQ_CHG__SHIFT, 0, 0x1 },
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_STATUS },
{ CMD_WAITFOR, mmGCK_SMC_IND_DATA, CG_SPLL_STATUS__SPLL_CHG_STATUS_MASK, 0, 0xffffffff, 0x2 },
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL_2 },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL_2__SPLL_CTLREQ_CHG_MASK, CG_SPLL_FUNC_CNTL_2__SPLL_CTLREQ_CHG__SHIFT, 0, 0x0 },
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC0500170 },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x4000000, 0x1a, 0, 0x1 },
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixMPLL_BYPASSCLK_SEL },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL_MASK, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL__SHIFT, 0, 0x2 }
};
static const struct baco_cmd_entry turn_off_plls_tbl[] =
{
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL__SPLL_RESET_MASK, CG_SPLL_FUNC_CNTL__SPLL_RESET__SHIFT, 0, 0x1 },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL__SPLL_PWRON_MASK, CG_SPLL_FUNC_CNTL__SPLL_PWRON__SHIFT, 0, 0x0 },
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC0500170 },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x2000000, 0x19, 0, 0x1 },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x8000000, 0x1b, 0, 0x0 }
};
static const struct baco_cmd_entry clk_req_b_tbl[] =
{
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_CLKPIN_CNTL_2 },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_CLKPIN_CNTL_2__FORCE_BIF_REFCLK_EN_MASK, CG_CLKPIN_CNTL_2__FORCE_BIF_REFCLK_EN__SHIFT, 0, 0x0 },
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixMPLL_BYPASSCLK_SEL },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL_MASK, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL__SHIFT, 0, 0x4 },
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixMISC_CLK_CTRL },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MISC_CLK_CTRL__DEEP_SLEEP_CLK_SEL_MASK, MISC_CLK_CTRL__DEEP_SLEEP_CLK_SEL__SHIFT, 0, 0x1 },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MISC_CLK_CTRL__ZCLK_SEL_MASK, MISC_CLK_CTRL__ZCLK_SEL__SHIFT, 0, 0x1 },
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_CLKPIN_CNTL },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_CLKPIN_CNTL__BCLK_AS_XCLK_MASK, CG_CLKPIN_CNTL__BCLK_AS_XCLK__SHIFT, 0, 0x0 },
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixTHM_CLK_CNTL },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, THM_CLK_CNTL__CMON_CLK_SEL_MASK, THM_CLK_CNTL__CMON_CLK_SEL__SHIFT, 0, 0x1 },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, THM_CLK_CNTL__TMON_CLK_SEL_MASK, THM_CLK_CNTL__TMON_CLK_SEL__SHIFT, 0, 0x1 }
};
static const struct baco_cmd_entry enter_baco_tbl[] =
{
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_EN_MASK, BACO_CNTL__BACO_EN__SHIFT, 0, 0x01 },
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BIF_SCLK_SWITCH_MASK, BACO_CNTL__BACO_BIF_SCLK_SWITCH__SHIFT, 0, 0x01 },
{ CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_BIF_SCLK_SWITCH_MASK, 0, 5, 0x40000 },
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BCLK_OFF_MASK, BACO_CNTL__BACO_BCLK_OFF__SHIFT, 0, 0x01 },
{ CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_BCLK_OFF_MASK, 0, 5, 0x02 },
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ISO_DIS_MASK, BACO_CNTL__BACO_ISO_DIS__SHIFT, 0, 0x00 },
{ CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_ISO_DIS_MASK, 0, 5, 0x00 },
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ANA_ISO_DIS_MASK, BACO_CNTL__BACO_ANA_ISO_DIS__SHIFT, 0, 0x00 },
{ CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_ANA_ISO_DIS_MASK, 0, 5, 0x00 },
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, BACO_CNTL__BACO_POWER_OFF__SHIFT, 0, 0x01 },
{ CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, 0, 5, 0x08 },
{ CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_MODE_MASK, 0, 0xffffffff, 0x40 }
};
#define BACO_CNTL__PWRGOOD_MASK BACO_CNTL__PWRGOOD_GPIO_MASK+BACO_CNTL__PWRGOOD_MEM_MASK+BACO_CNTL__PWRGOOD_DVO_MASK
static const struct baco_cmd_entry exit_baco_tbl[] =
{
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_RESET_EN_MASK, BACO_CNTL__BACO_RESET_EN__SHIFT, 0, 0x01 },
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BCLK_OFF_MASK, BACO_CNTL__BACO_BCLK_OFF__SHIFT, 0, 0x00 },
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, BACO_CNTL__BACO_POWER_OFF__SHIFT, 0, 0x00 },
{ CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__PWRGOOD_BF_MASK, 0, 0xffffffff, 0x200 },
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ISO_DIS_MASK, BACO_CNTL__BACO_ISO_DIS__SHIFT, 0, 0x01 },
{ CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__PWRGOOD_MASK, 0, 5, 0x1c00 },
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ANA_ISO_DIS_MASK, BACO_CNTL__BACO_ANA_ISO_DIS__SHIFT, 0, 0x01 },
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BIF_SCLK_SWITCH_MASK, BACO_CNTL__BACO_BIF_SCLK_SWITCH__SHIFT, 0, 0x00 },
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_RESET_EN_MASK, BACO_CNTL__BACO_RESET_EN__SHIFT, 0, 0x00 },
{ CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__RCU_BIF_CONFIG_DONE_MASK, 0, 5, 0x100 },
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_EN_MASK, BACO_CNTL__BACO_EN__SHIFT, 0, 0x00 },
{ CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_MODE_MASK, 0, 0xffffffff, 0x00 }
};
static const struct baco_cmd_entry clean_baco_tbl[] =
{
{ CMD_WRITE, mmBIOS_SCRATCH_0, 0, 0, 0, 0 },
{ CMD_WRITE, mmBIOS_SCRATCH_1, 0, 0, 0, 0 },
{ CMD_WRITE, mmBIOS_SCRATCH_2, 0, 0, 0, 0 },
{ CMD_WRITE, mmBIOS_SCRATCH_3, 0, 0, 0, 0 },
{ CMD_WRITE, mmBIOS_SCRATCH_4, 0, 0, 0, 0 },
{ CMD_WRITE, mmBIOS_SCRATCH_5, 0, 0, 0, 0 },
{ CMD_WRITE, mmBIOS_SCRATCH_6, 0, 0, 0, 0 },
{ CMD_WRITE, mmBIOS_SCRATCH_7, 0, 0, 0, 0 },
{ CMD_WRITE, mmBIOS_SCRATCH_8, 0, 0, 0, 0 },
{ CMD_WRITE, mmBIOS_SCRATCH_9, 0, 0, 0, 0 },
{ CMD_WRITE, mmBIOS_SCRATCH_10, 0, 0, 0, 0 },
{ CMD_WRITE, mmBIOS_SCRATCH_11, 0, 0, 0, 0 },
{ CMD_WRITE, mmBIOS_SCRATCH_12, 0, 0, 0, 0 },
{ CMD_WRITE, mmBIOS_SCRATCH_13, 0, 0, 0, 0 },
{ CMD_WRITE, mmBIOS_SCRATCH_14, 0, 0, 0, 0 },
{ CMD_WRITE, mmBIOS_SCRATCH_15, 0, 0, 0, 0 }
};
int fiji_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state)
{
enum BACO_STATE cur_state;
smu7_baco_get_state(hwmgr, &cur_state);
if (cur_state == state)
/* aisc already in the target state */
return 0;
if (state == BACO_STATE_IN) {
baco_program_registers(hwmgr, gpio_tbl, ARRAY_SIZE(gpio_tbl));
baco_program_registers(hwmgr, enable_fb_req_rej_tbl,
ARRAY_SIZE(enable_fb_req_rej_tbl));
baco_program_registers(hwmgr, use_bclk_tbl, ARRAY_SIZE(use_bclk_tbl));
baco_program_registers(hwmgr, turn_off_plls_tbl,
ARRAY_SIZE(turn_off_plls_tbl));
baco_program_registers(hwmgr, clk_req_b_tbl, ARRAY_SIZE(clk_req_b_tbl));
if (baco_program_registers(hwmgr, enter_baco_tbl,
ARRAY_SIZE(enter_baco_tbl)))
return 0;
} else if (state == BACO_STATE_OUT) {
/* HW requires at least 20ms between regulator off and on */
msleep(20);
/* Execute Hardware BACO exit sequence */
if (baco_program_registers(hwmgr, exit_baco_tbl,
ARRAY_SIZE(exit_baco_tbl))) {
if (baco_program_registers(hwmgr, clean_baco_tbl,
ARRAY_SIZE(clean_baco_tbl)))
return 0;
}
}
return -EINVAL;
}

View File

@@ -0,0 +1,29 @@
/*
* Copyright 2019 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.
*
*/
#ifndef __FIJI_BACO_H__
#define __FIJI_BACO_H__
#include "smu7_baco.h"
extern int fiji_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state);
#endif

View File

@@ -0,0 +1,547 @@
/*
* Copyright 2015 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 "pp_debug.h"
#include <linux/errno.h>
#include "hwmgr.h"
#include "hardwaremanager.h"
#include "power_state.h"
#define TEMP_RANGE_MIN (0)
#define TEMP_RANGE_MAX (80 * 1000)
#define PHM_FUNC_CHECK(hw) \
do { \
if ((hw) == NULL || (hw)->hwmgr_func == NULL) \
return -EINVAL; \
} while (0)
int phm_setup_asic(struct pp_hwmgr *hwmgr)
{
PHM_FUNC_CHECK(hwmgr);
if (NULL != hwmgr->hwmgr_func->asic_setup)
return hwmgr->hwmgr_func->asic_setup(hwmgr);
return 0;
}
int phm_power_down_asic(struct pp_hwmgr *hwmgr)
{
PHM_FUNC_CHECK(hwmgr);
if (NULL != hwmgr->hwmgr_func->power_off_asic)
return hwmgr->hwmgr_func->power_off_asic(hwmgr);
return 0;
}
int phm_set_power_state(struct pp_hwmgr *hwmgr,
const struct pp_hw_power_state *pcurrent_state,
const struct pp_hw_power_state *pnew_power_state)
{
struct phm_set_power_state_input states;
PHM_FUNC_CHECK(hwmgr);
states.pcurrent_state = pcurrent_state;
states.pnew_state = pnew_power_state;
if (NULL != hwmgr->hwmgr_func->power_state_set)
return hwmgr->hwmgr_func->power_state_set(hwmgr, &states);
return 0;
}
int phm_enable_dynamic_state_management(struct pp_hwmgr *hwmgr)
{
struct amdgpu_device *adev = NULL;
int ret = -EINVAL;
PHM_FUNC_CHECK(hwmgr);
adev = hwmgr->adev;
/* Skip for suspend/resume case */
if (!hwmgr->pp_one_vf && smum_is_dpm_running(hwmgr)
&& !amdgpu_passthrough(adev) && adev->in_suspend) {
pr_info("dpm has been enabled\n");
return 0;
}
if (NULL != hwmgr->hwmgr_func->dynamic_state_management_enable)
ret = hwmgr->hwmgr_func->dynamic_state_management_enable(hwmgr);
return ret;
}
int phm_disable_dynamic_state_management(struct pp_hwmgr *hwmgr)
{
int ret = -EINVAL;
PHM_FUNC_CHECK(hwmgr);
if (!hwmgr->not_vf)
return 0;
if (!smum_is_dpm_running(hwmgr)) {
pr_info("dpm has been disabled\n");
return 0;
}
if (hwmgr->hwmgr_func->dynamic_state_management_disable)
ret = hwmgr->hwmgr_func->dynamic_state_management_disable(hwmgr);
return ret;
}
int phm_force_dpm_levels(struct pp_hwmgr *hwmgr, enum amd_dpm_forced_level level)
{
int ret = 0;
PHM_FUNC_CHECK(hwmgr);
if (hwmgr->hwmgr_func->force_dpm_level != NULL)
ret = hwmgr->hwmgr_func->force_dpm_level(hwmgr, level);
return ret;
}
int phm_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,
struct pp_power_state *adjusted_ps,
const struct pp_power_state *current_ps)
{
PHM_FUNC_CHECK(hwmgr);
if (hwmgr->hwmgr_func->apply_state_adjust_rules != NULL)
return hwmgr->hwmgr_func->apply_state_adjust_rules(
hwmgr,
adjusted_ps,
current_ps);
return 0;
}
int phm_apply_clock_adjust_rules(struct pp_hwmgr *hwmgr)
{
PHM_FUNC_CHECK(hwmgr);
if (hwmgr->hwmgr_func->apply_clocks_adjust_rules != NULL)
return hwmgr->hwmgr_func->apply_clocks_adjust_rules(hwmgr);
return 0;
}
int phm_powerdown_uvd(struct pp_hwmgr *hwmgr)
{
PHM_FUNC_CHECK(hwmgr);
if (hwmgr->hwmgr_func->powerdown_uvd != NULL)
return hwmgr->hwmgr_func->powerdown_uvd(hwmgr);
return 0;
}
int phm_disable_clock_power_gatings(struct pp_hwmgr *hwmgr)
{
PHM_FUNC_CHECK(hwmgr);
if (NULL != hwmgr->hwmgr_func->disable_clock_power_gating)
return hwmgr->hwmgr_func->disable_clock_power_gating(hwmgr);
return 0;
}
int phm_pre_display_configuration_changed(struct pp_hwmgr *hwmgr)
{
PHM_FUNC_CHECK(hwmgr);
if (NULL != hwmgr->hwmgr_func->pre_display_config_changed)
hwmgr->hwmgr_func->pre_display_config_changed(hwmgr);
return 0;
}
int phm_display_configuration_changed(struct pp_hwmgr *hwmgr)
{
PHM_FUNC_CHECK(hwmgr);
if (NULL != hwmgr->hwmgr_func->display_config_changed)
hwmgr->hwmgr_func->display_config_changed(hwmgr);
return 0;
}
int phm_notify_smc_display_config_after_ps_adjustment(struct pp_hwmgr *hwmgr)
{
PHM_FUNC_CHECK(hwmgr);
if (NULL != hwmgr->hwmgr_func->notify_smc_display_config_after_ps_adjustment)
hwmgr->hwmgr_func->notify_smc_display_config_after_ps_adjustment(hwmgr);
return 0;
}
int phm_stop_thermal_controller(struct pp_hwmgr *hwmgr)
{
PHM_FUNC_CHECK(hwmgr);
if (!hwmgr->not_vf)
return 0;
if (hwmgr->hwmgr_func->stop_thermal_controller == NULL)
return -EINVAL;
return hwmgr->hwmgr_func->stop_thermal_controller(hwmgr);
}
int phm_register_irq_handlers(struct pp_hwmgr *hwmgr)
{
PHM_FUNC_CHECK(hwmgr);
if (hwmgr->hwmgr_func->register_irq_handlers != NULL)
return hwmgr->hwmgr_func->register_irq_handlers(hwmgr);
return 0;
}
/**
* Initializes the thermal controller subsystem.
*
* @param pHwMgr the address of the powerplay hardware manager.
* @exception PP_Result_Failed if any of the paramters is NULL, otherwise the return value from the dispatcher.
*/
int phm_start_thermal_controller(struct pp_hwmgr *hwmgr)
{
int ret = 0;
struct PP_TemperatureRange range = {
TEMP_RANGE_MIN,
TEMP_RANGE_MAX,
TEMP_RANGE_MAX,
TEMP_RANGE_MIN,
TEMP_RANGE_MAX,
TEMP_RANGE_MAX,
TEMP_RANGE_MIN,
TEMP_RANGE_MAX,
TEMP_RANGE_MAX};
struct amdgpu_device *adev = hwmgr->adev;
if (!hwmgr->not_vf)
return 0;
if (hwmgr->hwmgr_func->get_thermal_temperature_range)
hwmgr->hwmgr_func->get_thermal_temperature_range(
hwmgr, &range);
if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_ThermalController)
&& hwmgr->hwmgr_func->start_thermal_controller != NULL)
ret = hwmgr->hwmgr_func->start_thermal_controller(hwmgr, &range);
adev->pm.dpm.thermal.min_temp = range.min;
adev->pm.dpm.thermal.max_temp = range.max;
adev->pm.dpm.thermal.max_edge_emergency_temp = range.edge_emergency_max;
adev->pm.dpm.thermal.min_hotspot_temp = range.hotspot_min;
adev->pm.dpm.thermal.max_hotspot_crit_temp = range.hotspot_crit_max;
adev->pm.dpm.thermal.max_hotspot_emergency_temp = range.hotspot_emergency_max;
adev->pm.dpm.thermal.min_mem_temp = range.mem_min;
adev->pm.dpm.thermal.max_mem_crit_temp = range.mem_crit_max;
adev->pm.dpm.thermal.max_mem_emergency_temp = range.mem_emergency_max;
return ret;
}
bool phm_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr)
{
if (hwmgr == NULL ||
hwmgr->hwmgr_func == NULL)
return false;
if (hwmgr->pp_one_vf)
return false;
if (hwmgr->hwmgr_func->check_smc_update_required_for_display_configuration == NULL)
return false;
return hwmgr->hwmgr_func->check_smc_update_required_for_display_configuration(hwmgr);
}
int phm_check_states_equal(struct pp_hwmgr *hwmgr,
const struct pp_hw_power_state *pstate1,
const struct pp_hw_power_state *pstate2,
bool *equal)
{
PHM_FUNC_CHECK(hwmgr);
if (hwmgr->hwmgr_func->check_states_equal == NULL)
return -EINVAL;
return hwmgr->hwmgr_func->check_states_equal(hwmgr, pstate1, pstate2, equal);
}
int phm_store_dal_configuration_data(struct pp_hwmgr *hwmgr,
const struct amd_pp_display_configuration *display_config)
{
int index = 0;
int number_of_active_display = 0;
PHM_FUNC_CHECK(hwmgr);
if (display_config == NULL)
return -EINVAL;
if (NULL != hwmgr->hwmgr_func->set_min_deep_sleep_dcefclk)
hwmgr->hwmgr_func->set_min_deep_sleep_dcefclk(hwmgr, display_config->min_dcef_deep_sleep_set_clk);
for (index = 0; index < display_config->num_path_including_non_display; index++) {
if (display_config->displays[index].controller_id != 0)
number_of_active_display++;
}
if (NULL != hwmgr->hwmgr_func->set_active_display_count)
hwmgr->hwmgr_func->set_active_display_count(hwmgr, number_of_active_display);
if (hwmgr->hwmgr_func->store_cc6_data == NULL)
return -EINVAL;
/* TODO: pass other display configuration in the future */
if (hwmgr->hwmgr_func->store_cc6_data)
hwmgr->hwmgr_func->store_cc6_data(hwmgr,
display_config->cpu_pstate_separation_time,
display_config->cpu_cc6_disable,
display_config->cpu_pstate_disable,
display_config->nb_pstate_switch_disable);
return 0;
}
int phm_get_dal_power_level(struct pp_hwmgr *hwmgr,
struct amd_pp_simple_clock_info *info)
{
PHM_FUNC_CHECK(hwmgr);
if (info == NULL || hwmgr->hwmgr_func->get_dal_power_level == NULL)
return -EINVAL;
return hwmgr->hwmgr_func->get_dal_power_level(hwmgr, info);
}
int phm_set_cpu_power_state(struct pp_hwmgr *hwmgr)
{
PHM_FUNC_CHECK(hwmgr);
if (hwmgr->hwmgr_func->set_cpu_power_state != NULL)
return hwmgr->hwmgr_func->set_cpu_power_state(hwmgr);
return 0;
}
int phm_get_performance_level(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state,
PHM_PerformanceLevelDesignation designation, uint32_t index,
PHM_PerformanceLevel *level)
{
PHM_FUNC_CHECK(hwmgr);
if (hwmgr->hwmgr_func->get_performance_level == NULL)
return -EINVAL;
return hwmgr->hwmgr_func->get_performance_level(hwmgr, state, designation, index, level);
}
/**
* Gets Clock Info.
*
* @param pHwMgr the address of the powerplay hardware manager.
* @param pPowerState the address of the Power State structure.
* @param pClockInfo the address of PP_ClockInfo structure where the result will be returned.
* @exception PP_Result_Failed if any of the paramters is NULL, otherwise the return value from the back-end.
*/
int phm_get_clock_info(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state, struct pp_clock_info *pclock_info,
PHM_PerformanceLevelDesignation designation)
{
int result;
PHM_PerformanceLevel performance_level = {0};
PHM_FUNC_CHECK(hwmgr);
PP_ASSERT_WITH_CODE((NULL != state), "Invalid Input!", return -EINVAL);
PP_ASSERT_WITH_CODE((NULL != pclock_info), "Invalid Input!", return -EINVAL);
result = phm_get_performance_level(hwmgr, state, PHM_PerformanceLevelDesignation_Activity, 0, &performance_level);
PP_ASSERT_WITH_CODE((0 == result), "Failed to retrieve minimum clocks.", return result);
pclock_info->min_mem_clk = performance_level.memory_clock;
pclock_info->min_eng_clk = performance_level.coreClock;
pclock_info->min_bus_bandwidth = performance_level.nonLocalMemoryFreq * performance_level.nonLocalMemoryWidth;
result = phm_get_performance_level(hwmgr, state, designation,
(hwmgr->platform_descriptor.hardwareActivityPerformanceLevels - 1), &performance_level);
PP_ASSERT_WITH_CODE((0 == result), "Failed to retrieve maximum clocks.", return result);
pclock_info->max_mem_clk = performance_level.memory_clock;
pclock_info->max_eng_clk = performance_level.coreClock;
pclock_info->max_bus_bandwidth = performance_level.nonLocalMemoryFreq * performance_level.nonLocalMemoryWidth;
return 0;
}
int phm_get_current_shallow_sleep_clocks(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state, struct pp_clock_info *clock_info)
{
PHM_FUNC_CHECK(hwmgr);
if (hwmgr->hwmgr_func->get_current_shallow_sleep_clocks == NULL)
return -EINVAL;
return hwmgr->hwmgr_func->get_current_shallow_sleep_clocks(hwmgr, state, clock_info);
}
int phm_get_clock_by_type(struct pp_hwmgr *hwmgr, enum amd_pp_clock_type type, struct amd_pp_clocks *clocks)
{
PHM_FUNC_CHECK(hwmgr);
if (hwmgr->hwmgr_func->get_clock_by_type == NULL)
return -EINVAL;
return hwmgr->hwmgr_func->get_clock_by_type(hwmgr, type, clocks);
}
int phm_get_clock_by_type_with_latency(struct pp_hwmgr *hwmgr,
enum amd_pp_clock_type type,
struct pp_clock_levels_with_latency *clocks)
{
PHM_FUNC_CHECK(hwmgr);
if (hwmgr->hwmgr_func->get_clock_by_type_with_latency == NULL)
return -EINVAL;
return hwmgr->hwmgr_func->get_clock_by_type_with_latency(hwmgr, type, clocks);
}
int phm_get_clock_by_type_with_voltage(struct pp_hwmgr *hwmgr,
enum amd_pp_clock_type type,
struct pp_clock_levels_with_voltage *clocks)
{
PHM_FUNC_CHECK(hwmgr);
if (hwmgr->hwmgr_func->get_clock_by_type_with_voltage == NULL)
return -EINVAL;
return hwmgr->hwmgr_func->get_clock_by_type_with_voltage(hwmgr, type, clocks);
}
int phm_set_watermarks_for_clocks_ranges(struct pp_hwmgr *hwmgr,
void *clock_ranges)
{
PHM_FUNC_CHECK(hwmgr);
if (!hwmgr->hwmgr_func->set_watermarks_for_clocks_ranges)
return -EINVAL;
return hwmgr->hwmgr_func->set_watermarks_for_clocks_ranges(hwmgr,
clock_ranges);
}
int phm_display_clock_voltage_request(struct pp_hwmgr *hwmgr,
struct pp_display_clock_request *clock)
{
PHM_FUNC_CHECK(hwmgr);
if (!hwmgr->hwmgr_func->display_clock_voltage_request)
return -EINVAL;
return hwmgr->hwmgr_func->display_clock_voltage_request(hwmgr, clock);
}
int phm_get_max_high_clocks(struct pp_hwmgr *hwmgr, struct amd_pp_simple_clock_info *clocks)
{
PHM_FUNC_CHECK(hwmgr);
if (hwmgr->hwmgr_func->get_max_high_clocks == NULL)
return -EINVAL;
return hwmgr->hwmgr_func->get_max_high_clocks(hwmgr, clocks);
}
int phm_disable_smc_firmware_ctf(struct pp_hwmgr *hwmgr)
{
PHM_FUNC_CHECK(hwmgr);
if (!hwmgr->not_vf)
return 0;
if (hwmgr->hwmgr_func->disable_smc_firmware_ctf == NULL)
return -EINVAL;
return hwmgr->hwmgr_func->disable_smc_firmware_ctf(hwmgr);
}
int phm_set_active_display_count(struct pp_hwmgr *hwmgr, uint32_t count)
{
PHM_FUNC_CHECK(hwmgr);
if (!hwmgr->hwmgr_func->set_active_display_count)
return -EINVAL;
return hwmgr->hwmgr_func->set_active_display_count(hwmgr, count);
}
int phm_set_min_deep_sleep_dcefclk(struct pp_hwmgr *hwmgr, uint32_t clock)
{
PHM_FUNC_CHECK(hwmgr);
if (!hwmgr->hwmgr_func->set_min_deep_sleep_dcefclk)
return -EINVAL;
return hwmgr->hwmgr_func->set_min_deep_sleep_dcefclk(hwmgr, clock);
}
int phm_set_hard_min_dcefclk_by_freq(struct pp_hwmgr *hwmgr, uint32_t clock)
{
PHM_FUNC_CHECK(hwmgr);
if (!hwmgr->hwmgr_func->set_hard_min_dcefclk_by_freq)
return -EINVAL;
return hwmgr->hwmgr_func->set_hard_min_dcefclk_by_freq(hwmgr, clock);
}
int phm_set_hard_min_fclk_by_freq(struct pp_hwmgr *hwmgr, uint32_t clock)
{
PHM_FUNC_CHECK(hwmgr);
if (!hwmgr->hwmgr_func->set_hard_min_fclk_by_freq)
return -EINVAL;
return hwmgr->hwmgr_func->set_hard_min_fclk_by_freq(hwmgr, clock);
}

View File

@@ -0,0 +1,564 @@
/*
* Copyright 2015 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 "pp_debug.h"
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/pci.h>
#include <drm/amdgpu_drm.h>
#include "power_state.h"
#include "hwmgr.h"
#include "ppsmc.h"
#include "amd_acpi.h"
#include "pp_psm.h"
extern const struct pp_smumgr_func ci_smu_funcs;
extern const struct pp_smumgr_func smu8_smu_funcs;
extern const struct pp_smumgr_func iceland_smu_funcs;
extern const struct pp_smumgr_func tonga_smu_funcs;
extern const struct pp_smumgr_func fiji_smu_funcs;
extern const struct pp_smumgr_func polaris10_smu_funcs;
extern const struct pp_smumgr_func vegam_smu_funcs;
extern const struct pp_smumgr_func vega10_smu_funcs;
extern const struct pp_smumgr_func vega12_smu_funcs;
extern const struct pp_smumgr_func smu10_smu_funcs;
extern const struct pp_smumgr_func vega20_smu_funcs;
extern int smu7_init_function_pointers(struct pp_hwmgr *hwmgr);
extern int smu8_init_function_pointers(struct pp_hwmgr *hwmgr);
extern int vega10_hwmgr_init(struct pp_hwmgr *hwmgr);
extern int vega12_hwmgr_init(struct pp_hwmgr *hwmgr);
extern int vega20_hwmgr_init(struct pp_hwmgr *hwmgr);
extern int smu10_init_function_pointers(struct pp_hwmgr *hwmgr);
static int polaris_set_asic_special_caps(struct pp_hwmgr *hwmgr);
static void hwmgr_init_default_caps(struct pp_hwmgr *hwmgr);
static int hwmgr_set_user_specify_caps(struct pp_hwmgr *hwmgr);
static int fiji_set_asic_special_caps(struct pp_hwmgr *hwmgr);
static int tonga_set_asic_special_caps(struct pp_hwmgr *hwmgr);
static int topaz_set_asic_special_caps(struct pp_hwmgr *hwmgr);
static int ci_set_asic_special_caps(struct pp_hwmgr *hwmgr);
static void hwmgr_init_workload_prority(struct pp_hwmgr *hwmgr)
{
hwmgr->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT] = 0;
hwmgr->workload_prority[PP_SMC_POWER_PROFILE_FULLSCREEN3D] = 1;
hwmgr->workload_prority[PP_SMC_POWER_PROFILE_POWERSAVING] = 2;
hwmgr->workload_prority[PP_SMC_POWER_PROFILE_VIDEO] = 3;
hwmgr->workload_prority[PP_SMC_POWER_PROFILE_VR] = 4;
hwmgr->workload_prority[PP_SMC_POWER_PROFILE_COMPUTE] = 5;
hwmgr->workload_setting[0] = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
hwmgr->workload_setting[1] = PP_SMC_POWER_PROFILE_FULLSCREEN3D;
hwmgr->workload_setting[2] = PP_SMC_POWER_PROFILE_POWERSAVING;
hwmgr->workload_setting[3] = PP_SMC_POWER_PROFILE_VIDEO;
hwmgr->workload_setting[4] = PP_SMC_POWER_PROFILE_VR;
hwmgr->workload_setting[5] = PP_SMC_POWER_PROFILE_COMPUTE;
}
int hwmgr_early_init(struct pp_hwmgr *hwmgr)
{
struct amdgpu_device *adev;
if (!hwmgr)
return -EINVAL;
hwmgr->usec_timeout = AMD_MAX_USEC_TIMEOUT;
hwmgr->pp_table_version = PP_TABLE_V1;
hwmgr->dpm_level = AMD_DPM_FORCED_LEVEL_AUTO;
hwmgr->request_dpm_level = AMD_DPM_FORCED_LEVEL_AUTO;
hwmgr_init_default_caps(hwmgr);
hwmgr_set_user_specify_caps(hwmgr);
hwmgr->fan_ctrl_is_in_default_mode = true;
hwmgr_init_workload_prority(hwmgr);
hwmgr->gfxoff_state_changed_by_workload = false;
adev = hwmgr->adev;
switch (hwmgr->chip_family) {
case AMDGPU_FAMILY_CI:
adev->pm.pp_feature &= ~PP_GFXOFF_MASK;
hwmgr->smumgr_funcs = &ci_smu_funcs;
ci_set_asic_special_caps(hwmgr);
hwmgr->feature_mask &= ~(PP_VBI_TIME_SUPPORT_MASK |
PP_ENABLE_GFX_CG_THRU_SMU |
PP_GFXOFF_MASK);
hwmgr->pp_table_version = PP_TABLE_V0;
hwmgr->od_enabled = false;
smu7_init_function_pointers(hwmgr);
break;
case AMDGPU_FAMILY_CZ:
adev->pm.pp_feature &= ~PP_GFXOFF_MASK;
hwmgr->od_enabled = false;
hwmgr->smumgr_funcs = &smu8_smu_funcs;
hwmgr->feature_mask &= ~PP_GFXOFF_MASK;
smu8_init_function_pointers(hwmgr);
break;
case AMDGPU_FAMILY_VI:
adev->pm.pp_feature &= ~PP_GFXOFF_MASK;
hwmgr->feature_mask &= ~PP_GFXOFF_MASK;
switch (hwmgr->chip_id) {
case CHIP_TOPAZ:
hwmgr->smumgr_funcs = &iceland_smu_funcs;
topaz_set_asic_special_caps(hwmgr);
hwmgr->feature_mask &= ~ (PP_VBI_TIME_SUPPORT_MASK |
PP_ENABLE_GFX_CG_THRU_SMU);
hwmgr->pp_table_version = PP_TABLE_V0;
hwmgr->od_enabled = false;
break;
case CHIP_TONGA:
hwmgr->smumgr_funcs = &tonga_smu_funcs;
tonga_set_asic_special_caps(hwmgr);
hwmgr->feature_mask &= ~PP_VBI_TIME_SUPPORT_MASK;
break;
case CHIP_FIJI:
hwmgr->smumgr_funcs = &fiji_smu_funcs;
fiji_set_asic_special_caps(hwmgr);
hwmgr->feature_mask &= ~ (PP_VBI_TIME_SUPPORT_MASK |
PP_ENABLE_GFX_CG_THRU_SMU);
break;
case CHIP_POLARIS11:
case CHIP_POLARIS10:
case CHIP_POLARIS12:
hwmgr->smumgr_funcs = &polaris10_smu_funcs;
polaris_set_asic_special_caps(hwmgr);
hwmgr->feature_mask &= ~(PP_UVD_HANDSHAKE_MASK);
break;
case CHIP_VEGAM:
hwmgr->smumgr_funcs = &vegam_smu_funcs;
polaris_set_asic_special_caps(hwmgr);
hwmgr->feature_mask &= ~(PP_UVD_HANDSHAKE_MASK);
break;
default:
return -EINVAL;
}
smu7_init_function_pointers(hwmgr);
break;
case AMDGPU_FAMILY_AI:
switch (hwmgr->chip_id) {
case CHIP_VEGA10:
adev->pm.pp_feature &= ~PP_GFXOFF_MASK;
hwmgr->feature_mask &= ~PP_GFXOFF_MASK;
hwmgr->smumgr_funcs = &vega10_smu_funcs;
vega10_hwmgr_init(hwmgr);
break;
case CHIP_VEGA12:
hwmgr->smumgr_funcs = &vega12_smu_funcs;
vega12_hwmgr_init(hwmgr);
break;
case CHIP_VEGA20:
adev->pm.pp_feature &= ~PP_GFXOFF_MASK;
hwmgr->feature_mask &= ~PP_GFXOFF_MASK;
hwmgr->smumgr_funcs = &vega20_smu_funcs;
vega20_hwmgr_init(hwmgr);
break;
default:
return -EINVAL;
}
break;
case AMDGPU_FAMILY_RV:
switch (hwmgr->chip_id) {
case CHIP_RAVEN:
hwmgr->od_enabled = false;
hwmgr->smumgr_funcs = &smu10_smu_funcs;
smu10_init_function_pointers(hwmgr);
break;
default:
return -EINVAL;
}
break;
default:
return -EINVAL;
}
return 0;
}
int hwmgr_sw_init(struct pp_hwmgr *hwmgr)
{
if (!hwmgr|| !hwmgr->smumgr_funcs || !hwmgr->smumgr_funcs->smu_init)
return -EINVAL;
phm_register_irq_handlers(hwmgr);
pr_info("hwmgr_sw_init smu backed is %s\n", hwmgr->smumgr_funcs->name);
return hwmgr->smumgr_funcs->smu_init(hwmgr);
}
int hwmgr_sw_fini(struct pp_hwmgr *hwmgr)
{
if (hwmgr && hwmgr->smumgr_funcs && hwmgr->smumgr_funcs->smu_fini)
hwmgr->smumgr_funcs->smu_fini(hwmgr);
return 0;
}
int hwmgr_hw_init(struct pp_hwmgr *hwmgr)
{
int ret = 0;
hwmgr->pp_one_vf = amdgpu_sriov_is_pp_one_vf((struct amdgpu_device *)hwmgr->adev);
hwmgr->pm_en = (amdgpu_dpm && (hwmgr->not_vf || hwmgr->pp_one_vf))
? true : false;
if (!hwmgr->pm_en)
return 0;
if (!hwmgr->pptable_func ||
!hwmgr->pptable_func->pptable_init ||
!hwmgr->hwmgr_func->backend_init) {
hwmgr->pm_en = false;
pr_info("dpm not supported \n");
return 0;
}
ret = hwmgr->pptable_func->pptable_init(hwmgr);
if (ret)
goto err;
((struct amdgpu_device *)hwmgr->adev)->pm.no_fan =
hwmgr->thermal_controller.fanInfo.bNoFan;
ret = hwmgr->hwmgr_func->backend_init(hwmgr);
if (ret)
goto err1;
/* make sure dc limits are valid */
if ((hwmgr->dyn_state.max_clock_voltage_on_dc.sclk == 0) ||
(hwmgr->dyn_state.max_clock_voltage_on_dc.mclk == 0))
hwmgr->dyn_state.max_clock_voltage_on_dc =
hwmgr->dyn_state.max_clock_voltage_on_ac;
ret = psm_init_power_state_table(hwmgr);
if (ret)
goto err2;
ret = phm_setup_asic(hwmgr);
if (ret)
goto err2;
ret = phm_enable_dynamic_state_management(hwmgr);
if (ret)
goto err2;
ret = phm_start_thermal_controller(hwmgr);
ret |= psm_set_performance_states(hwmgr);
if (ret)
goto err2;
((struct amdgpu_device *)hwmgr->adev)->pm.dpm_enabled = true;
return 0;
err2:
if (hwmgr->hwmgr_func->backend_fini)
hwmgr->hwmgr_func->backend_fini(hwmgr);
err1:
if (hwmgr->pptable_func->pptable_fini)
hwmgr->pptable_func->pptable_fini(hwmgr);
err:
return ret;
}
int hwmgr_hw_fini(struct pp_hwmgr *hwmgr)
{
if (!hwmgr || !hwmgr->pm_en || !hwmgr->not_vf)
return 0;
phm_stop_thermal_controller(hwmgr);
psm_set_boot_states(hwmgr);
psm_adjust_power_state_dynamic(hwmgr, true, NULL);
phm_disable_dynamic_state_management(hwmgr);
phm_disable_clock_power_gatings(hwmgr);
if (hwmgr->hwmgr_func->backend_fini)
hwmgr->hwmgr_func->backend_fini(hwmgr);
if (hwmgr->pptable_func->pptable_fini)
hwmgr->pptable_func->pptable_fini(hwmgr);
return psm_fini_power_state_table(hwmgr);
}
int hwmgr_suspend(struct pp_hwmgr *hwmgr)
{
int ret = 0;
if (!hwmgr || !hwmgr->pm_en || !hwmgr->not_vf)
return 0;
phm_disable_smc_firmware_ctf(hwmgr);
ret = psm_set_boot_states(hwmgr);
if (ret)
return ret;
ret = psm_adjust_power_state_dynamic(hwmgr, true, NULL);
if (ret)
return ret;
ret = phm_power_down_asic(hwmgr);
return ret;
}
int hwmgr_resume(struct pp_hwmgr *hwmgr)
{
int ret = 0;
if (!hwmgr)
return -EINVAL;
if (!hwmgr->not_vf || !hwmgr->pm_en)
return 0;
ret = phm_setup_asic(hwmgr);
if (ret)
return ret;
ret = phm_enable_dynamic_state_management(hwmgr);
if (ret)
return ret;
ret = phm_start_thermal_controller(hwmgr);
ret |= psm_set_performance_states(hwmgr);
if (ret)
return ret;
ret = psm_adjust_power_state_dynamic(hwmgr, false, NULL);
return ret;
}
static enum PP_StateUILabel power_state_convert(enum amd_pm_state_type state)
{
switch (state) {
case POWER_STATE_TYPE_BATTERY:
return PP_StateUILabel_Battery;
case POWER_STATE_TYPE_BALANCED:
return PP_StateUILabel_Balanced;
case POWER_STATE_TYPE_PERFORMANCE:
return PP_StateUILabel_Performance;
default:
return PP_StateUILabel_None;
}
}
int hwmgr_handle_task(struct pp_hwmgr *hwmgr, enum amd_pp_task task_id,
enum amd_pm_state_type *user_state)
{
int ret = 0;
if (hwmgr == NULL)
return -EINVAL;
switch (task_id) {
case AMD_PP_TASK_DISPLAY_CONFIG_CHANGE:
if (!hwmgr->not_vf)
return ret;
ret = phm_pre_display_configuration_changed(hwmgr);
if (ret)
return ret;
ret = phm_set_cpu_power_state(hwmgr);
if (ret)
return ret;
ret = psm_set_performance_states(hwmgr);
if (ret)
return ret;
ret = psm_adjust_power_state_dynamic(hwmgr, false, NULL);
break;
case AMD_PP_TASK_ENABLE_USER_STATE:
{
enum PP_StateUILabel requested_ui_label;
struct pp_power_state *requested_ps = NULL;
if (!hwmgr->not_vf)
return ret;
if (user_state == NULL) {
ret = -EINVAL;
break;
}
requested_ui_label = power_state_convert(*user_state);
ret = psm_set_user_performance_state(hwmgr, requested_ui_label, &requested_ps);
if (ret)
return ret;
ret = psm_adjust_power_state_dynamic(hwmgr, true, requested_ps);
break;
}
case AMD_PP_TASK_COMPLETE_INIT:
case AMD_PP_TASK_READJUST_POWER_STATE:
ret = psm_adjust_power_state_dynamic(hwmgr, true, NULL);
break;
default:
break;
}
return ret;
}
void hwmgr_init_default_caps(struct pp_hwmgr *hwmgr)
{
phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PCIEPerformanceRequest);
phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_UVDDPM);
phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_VCEDPM);
#if defined(CONFIG_ACPI)
if (amdgpu_acpi_is_pcie_performance_request_supported(hwmgr->adev))
phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PCIEPerformanceRequest);
#endif
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_DynamicPatchPowerState);
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_EnableSMU7ThermalManagement);
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_DynamicPowerManagement);
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_SMC);
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_DynamicUVDState);
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_FanSpeedInTableIsRPM);
return;
}
int hwmgr_set_user_specify_caps(struct pp_hwmgr *hwmgr)
{
if (hwmgr->feature_mask & PP_SCLK_DEEP_SLEEP_MASK)
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_SclkDeepSleep);
else
phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_SclkDeepSleep);
if (hwmgr->feature_mask & PP_POWER_CONTAINMENT_MASK) {
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_PowerContainment);
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_CAC);
} else {
phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_PowerContainment);
phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_CAC);
}
if (hwmgr->feature_mask & PP_OVERDRIVE_MASK)
hwmgr->od_enabled = true;
return 0;
}
int polaris_set_asic_special_caps(struct pp_hwmgr *hwmgr)
{
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_EVV);
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_SQRamping);
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_RegulatorHot);
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_AutomaticDCTransition);
if (hwmgr->chip_id != CHIP_POLARIS10)
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_SPLLShutdownSupport);
if (hwmgr->chip_id != CHIP_POLARIS11) {
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_DBRamping);
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_TDRamping);
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_TCPRamping);
}
return 0;
}
int fiji_set_asic_special_caps(struct pp_hwmgr *hwmgr)
{
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_EVV);
phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_SQRamping);
phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_DBRamping);
phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_TDRamping);
phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_TCPRamping);
return 0;
}
int tonga_set_asic_special_caps(struct pp_hwmgr *hwmgr)
{
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_EVV);
phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_SQRamping);
phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_DBRamping);
phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_TDRamping);
phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_TCPRamping);
phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_UVDPowerGating);
phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_VCEPowerGating);
return 0;
}
int topaz_set_asic_special_caps(struct pp_hwmgr *hwmgr)
{
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_EVV);
phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_SQRamping);
phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_DBRamping);
phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_TDRamping);
phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_TCPRamping);
return 0;
}
int ci_set_asic_special_caps(struct pp_hwmgr *hwmgr)
{
phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_SQRamping);
phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_DBRamping);
phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_TDRamping);
phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_TCPRamping);
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_MemorySpreadSpectrumSupport);
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_EngineSpreadSpectrumSupport);
return 0;
}

View File

@@ -0,0 +1,116 @@
/*
* Copyright 2015 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.
*
*/
#ifndef PP_HWMGR_PPT_H
#define PP_HWMGR_PPT_H
#include "hardwaremanager.h"
#include "smumgr.h"
#include "atom-types.h"
struct phm_ppt_v1_clock_voltage_dependency_record {
uint32_t clk;
uint8_t vddInd;
uint8_t vddciInd;
uint8_t mvddInd;
uint16_t vdd_offset;
uint16_t vddc;
uint16_t vddgfx;
uint16_t vddci;
uint16_t mvdd;
uint8_t phases;
uint8_t cks_enable;
uint8_t cks_voffset;
uint32_t sclk_offset;
};
typedef struct phm_ppt_v1_clock_voltage_dependency_record phm_ppt_v1_clock_voltage_dependency_record;
struct phm_ppt_v1_clock_voltage_dependency_table {
uint32_t count; /* Number of entries. */
phm_ppt_v1_clock_voltage_dependency_record entries[1]; /* Dynamically allocate count entries. */
};
typedef struct phm_ppt_v1_clock_voltage_dependency_table phm_ppt_v1_clock_voltage_dependency_table;
/* Multimedia Clock Voltage Dependency records and table */
struct phm_ppt_v1_mm_clock_voltage_dependency_record {
uint32_t dclk; /* UVD D-clock */
uint32_t vclk; /* UVD V-clock */
uint32_t eclk; /* VCE clock */
uint32_t aclk; /* ACP clock */
uint32_t samclock; /* SAMU clock */
uint8_t vddcInd;
uint16_t vddgfx_offset;
uint16_t vddc;
uint16_t vddgfx;
uint8_t phases;
};
typedef struct phm_ppt_v1_mm_clock_voltage_dependency_record phm_ppt_v1_mm_clock_voltage_dependency_record;
struct phm_ppt_v1_mm_clock_voltage_dependency_table {
uint32_t count; /* Number of entries. */
phm_ppt_v1_mm_clock_voltage_dependency_record entries[1]; /* Dynamically allocate count entries. */
};
typedef struct phm_ppt_v1_mm_clock_voltage_dependency_table phm_ppt_v1_mm_clock_voltage_dependency_table;
struct phm_ppt_v1_voltage_lookup_record {
uint16_t us_calculated;
uint16_t us_vdd; /* Base voltage */
uint16_t us_cac_low;
uint16_t us_cac_mid;
uint16_t us_cac_high;
};
typedef struct phm_ppt_v1_voltage_lookup_record phm_ppt_v1_voltage_lookup_record;
struct phm_ppt_v1_voltage_lookup_table {
uint32_t count;
phm_ppt_v1_voltage_lookup_record entries[1]; /* Dynamically allocate count entries. */
};
typedef struct phm_ppt_v1_voltage_lookup_table phm_ppt_v1_voltage_lookup_table;
/* PCIE records and Table */
struct phm_ppt_v1_pcie_record {
uint8_t gen_speed;
uint8_t lane_width;
uint16_t usreserved;
uint16_t reserved;
uint32_t pcie_sclk;
};
typedef struct phm_ppt_v1_pcie_record phm_ppt_v1_pcie_record;
struct phm_ppt_v1_pcie_table {
uint32_t count; /* Number of entries. */
phm_ppt_v1_pcie_record entries[1]; /* Dynamically allocate count entries. */
};
typedef struct phm_ppt_v1_pcie_table phm_ppt_v1_pcie_table;
struct phm_ppt_v1_gpio_table {
uint8_t vrhot_triggered_sclk_dpm_index; /* SCLK DPM level index to switch to when VRHot is triggered */
};
typedef struct phm_ppt_v1_gpio_table phm_ppt_v1_gpio_table;
#endif

View File

@@ -0,0 +1,222 @@
/*
* Copyright 2019 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 "polaris_baco.h"
#include "gmc/gmc_8_1_d.h"
#include "gmc/gmc_8_1_sh_mask.h"
#include "bif/bif_5_0_d.h"
#include "bif/bif_5_0_sh_mask.h"
#include "dce/dce_11_0_d.h"
#include "dce/dce_11_0_sh_mask.h"
#include "smu/smu_7_1_3_d.h"
#include "smu/smu_7_1_3_sh_mask.h"
static const struct baco_cmd_entry gpio_tbl[] =
{
{ CMD_WRITE, mmGPIOPAD_EN, 0, 0, 0, 0x0 },
{ CMD_WRITE, mmGPIOPAD_PD_EN, 0, 0, 0, 0x0 },
{ CMD_WRITE, mmGPIOPAD_PU_EN, 0, 0, 0, 0x0 },
{ CMD_WRITE, mmGPIOPAD_MASK, 0, 0, 0, 0xff77ffff },
{ CMD_WRITE, mmDC_GPIO_DVODATA_EN, 0, 0, 0, 0x0 },
{ CMD_WRITE, mmDC_GPIO_DVODATA_MASK, 0, 0, 0, 0xffffffff },
{ CMD_WRITE, mmDC_GPIO_GENERIC_EN, 0, 0, 0, 0x0 },
{ CMD_READMODIFYWRITE, mmDC_GPIO_GENERIC_MASK, 0, 0, 0, 0x03333333 },
{ CMD_WRITE, mmDC_GPIO_SYNCA_EN, 0, 0, 0, 0x0 },
{ CMD_READMODIFYWRITE, mmDC_GPIO_SYNCA_MASK, 0, 0, 0, 0x00001111 }
};
static const struct baco_cmd_entry enable_fb_req_rej_tbl[] =
{
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC0300024 },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x1, 0x0, 0, 0x1 },
{ CMD_WRITE, mmBIF_FB_EN, 0, 0, 0, 0x0 }
};
static const struct baco_cmd_entry use_bclk_tbl[] =
{
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL__SPLL_BYPASS_EN_MASK, CG_SPLL_FUNC_CNTL__SPLL_BYPASS_EN__SHIFT, 0, 0x1 },
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC0500170 },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x4000000, 0x1a, 0, 0x1 },
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixGCK_DFS_BYPASS_CNTL },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, GCK_DFS_BYPASS_CNTL__BYPASSACLK_MASK, GCK_DFS_BYPASS_CNTL__BYPASSACLK__SHIFT, 0, 0x1 },
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixMPLL_BYPASSCLK_SEL },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL_MASK, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL__SHIFT, 0, 0x2 },
{ CMD_READMODIFYWRITE, mmMPLL_CNTL_MODE, MPLL_CNTL_MODE__MPLL_SW_DIR_CONTROL_MASK, MPLL_CNTL_MODE__MPLL_SW_DIR_CONTROL__SHIFT, 0, 0x1 },
{ CMD_READMODIFYWRITE, mmMPLL_CNTL_MODE, MPLL_CNTL_MODE__MPLL_MCLK_SEL_MASK, MPLL_CNTL_MODE__MPLL_MCLK_SEL__SHIFT, 0, 0x0 }
};
static const struct baco_cmd_entry turn_off_plls_tbl[] =
{
{ CMD_READMODIFYWRITE, mmDC_GPIO_PAD_STRENGTH_1, DC_GPIO_PAD_STRENGTH_1__GENLK_STRENGTH_SP_MASK, DC_GPIO_PAD_STRENGTH_1__GENLK_STRENGTH_SP__SHIFT, 0, 0x1 },
{ CMD_DELAY_US, 0, 0, 0, 1, 0x0 },
{ CMD_READMODIFYWRITE, mmMC_SEQ_DRAM, MC_SEQ_DRAM__RST_CTL_MASK, MC_SEQ_DRAM__RST_CTL__SHIFT, 0, 0x1 },
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC05002B0 },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x10, 0x4, 0, 0x1 },
{ CMD_WAITFOR, mmGCK_SMC_IND_DATA, 0x10, 0, 1, 0 },
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC050032C },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x10, 0x4, 0, 0x1 },
{ CMD_WAITFOR, mmGCK_SMC_IND_DATA, 0x10, 0, 1, 0 },
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC0500080 },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x1, 0x0, 0, 0x1 },
{ CMD_READMODIFYWRITE, 0xda2, 0x40, 0x6, 0, 0x0 },
{ CMD_DELAY_US, 0, 0, 0, 3, 0x0 },
{ CMD_READMODIFYWRITE, 0xda2, 0x8, 0x3, 0, 0x0 },
{ CMD_READMODIFYWRITE, 0xda2, 0x3fff00, 0x8, 0, 0x32 },
{ CMD_DELAY_US, 0, 0, 0, 3, 0x0 },
{ CMD_READMODIFYWRITE, mmMPLL_FUNC_CNTL_2, MPLL_FUNC_CNTL_2__ISO_DIS_P_MASK, MPLL_FUNC_CNTL_2__ISO_DIS_P__SHIFT, 0, 0x0 },
{ CMD_DELAY_US, 0, 0, 0, 5, 0x0 }
};
static const struct baco_cmd_entry clk_req_b_tbl[] =
{
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixTHM_CLK_CNTL },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, THM_CLK_CNTL__CMON_CLK_SEL_MASK, THM_CLK_CNTL__CMON_CLK_SEL__SHIFT, 0, 0x1 },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, THM_CLK_CNTL__TMON_CLK_SEL_MASK, THM_CLK_CNTL__TMON_CLK_SEL__SHIFT, 0, 0x1 },
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixMISC_CLK_CTRL },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MISC_CLK_CTRL__DEEP_SLEEP_CLK_SEL_MASK, MISC_CLK_CTRL__DEEP_SLEEP_CLK_SEL__SHIFT, 0, 0x1 },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MISC_CLK_CTRL__ZCLK_SEL_MASK, MISC_CLK_CTRL__ZCLK_SEL__SHIFT, 0, 0x1 },
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_CLKPIN_CNTL },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_CLKPIN_CNTL__BCLK_AS_XCLK_MASK, CG_CLKPIN_CNTL__BCLK_AS_XCLK__SHIFT, 0, 0x0 },
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_CLKPIN_CNTL_2 },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_CLKPIN_CNTL_2__FORCE_BIF_REFCLK_EN_MASK, CG_CLKPIN_CNTL_2__FORCE_BIF_REFCLK_EN__SHIFT, 0, 0x0 },
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixMPLL_BYPASSCLK_SEL },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL_MASK, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL__SHIFT, 0, 0x4 }
};
static const struct baco_cmd_entry enter_baco_tbl[] =
{
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_EN_MASK, BACO_CNTL__BACO_EN__SHIFT, 0, 0x01 },
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BIF_SCLK_SWITCH_MASK, BACO_CNTL__BACO_BIF_SCLK_SWITCH__SHIFT, 0, 0x01 },
{ CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_BIF_SCLK_SWITCH_MASK, 0, 5, 0x40000 },
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BCLK_OFF_MASK, BACO_CNTL__BACO_BCLK_OFF__SHIFT, 0, 0x01 },
{ CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_BCLK_OFF_MASK, 0, 5, 0x02 },
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ISO_DIS_MASK, BACO_CNTL__BACO_ISO_DIS__SHIFT, 0, 0x00 },
{ CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_ISO_DIS_MASK, 0, 5, 0x00 },
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ANA_ISO_DIS_MASK, BACO_CNTL__BACO_ANA_ISO_DIS__SHIFT, 0, 0x00 },
{ CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_ANA_ISO_DIS_MASK, 0, 5, 0x00 },
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, BACO_CNTL__BACO_POWER_OFF__SHIFT, 0, 0x01 },
{ CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, 0, 5, 0x08 },
{ CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_MODE_MASK, 0, 0xffffffff, 0x40 }
};
#define BACO_CNTL__PWRGOOD_MASK BACO_CNTL__PWRGOOD_GPIO_MASK+BACO_CNTL__PWRGOOD_MEM_MASK+BACO_CNTL__PWRGOOD_DVO_MASK
static const struct baco_cmd_entry exit_baco_tbl[] =
{
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_RESET_EN_MASK, BACO_CNTL__BACO_RESET_EN__SHIFT, 0, 0x01 },
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BCLK_OFF_MASK, BACO_CNTL__BACO_BCLK_OFF__SHIFT, 0, 0x00 },
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, BACO_CNTL__BACO_POWER_OFF__SHIFT, 0, 0x00 },
{ CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__PWRGOOD_BF_MASK, 0, 0xffffffff, 0x200 },
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ISO_DIS_MASK, BACO_CNTL__BACO_ISO_DIS__SHIFT, 0, 0x01 },
{ CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__PWRGOOD_MASK, 0, 5, 0x1c00 },
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ANA_ISO_DIS_MASK, BACO_CNTL__BACO_ANA_ISO_DIS__SHIFT, 0, 0x01 },
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BIF_SCLK_SWITCH_MASK, BACO_CNTL__BACO_BIF_SCLK_SWITCH__SHIFT, 0, 0x00 },
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_RESET_EN_MASK, BACO_CNTL__BACO_RESET_EN__SHIFT, 0, 0x00 },
{ CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__RCU_BIF_CONFIG_DONE_MASK, 0, 5, 0x100 },
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_EN_MASK, BACO_CNTL__BACO_EN__SHIFT, 0, 0x00 },
{ CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_MODE_MASK, 0, 0xffffffff, 0x00 }
};
static const struct baco_cmd_entry clean_baco_tbl[] =
{
{ CMD_WRITE, mmBIOS_SCRATCH_6, 0, 0, 0, 0 },
{ CMD_WRITE, mmBIOS_SCRATCH_7, 0, 0, 0, 0 }
};
static const struct baco_cmd_entry use_bclk_tbl_vg[] =
{
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL__SPLL_BYPASS_EN_MASK, CG_SPLL_FUNC_CNTL__SPLL_BYPASS_EN__SHIFT, 0, 0x1 },
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC0500170 },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x4000000, 0x1a, 0, 0x1 },
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixGCK_DFS_BYPASS_CNTL },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, GCK_DFS_BYPASS_CNTL__BYPASSACLK_MASK, GCK_DFS_BYPASS_CNTL__BYPASSACLK__SHIFT, 0, 0x1 },
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixMPLL_BYPASSCLK_SEL },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL_MASK, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL__SHIFT, 0, 0x2 }
};
static const struct baco_cmd_entry turn_off_plls_tbl_vg[] =
{
{ CMD_READMODIFYWRITE, mmDC_GPIO_PAD_STRENGTH_1, DC_GPIO_PAD_STRENGTH_1__GENLK_STRENGTH_SP_MASK, DC_GPIO_PAD_STRENGTH_1__GENLK_STRENGTH_SP__SHIFT, 0, 0x1 },
{ CMD_DELAY_US, 0, 0, 0, 1, 0x0 },
{ CMD_READMODIFYWRITE, mmMC_SEQ_DRAM, MC_SEQ_DRAM__RST_CTL_MASK, MC_SEQ_DRAM__RST_CTL__SHIFT, 0, 0x1 },
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC05002B0 },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x10, 0x4, 0, 0x1 },
{ CMD_WAITFOR, mmGCK_SMC_IND_DATA, 0x10, 0, 1, 0 },
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC050032C },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x10, 0x4, 0, 0x1 },
{ CMD_WAITFOR, mmGCK_SMC_IND_DATA, 0x10, 0, 1, 0 },
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC0500080 },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x1, 0x0, 0, 0x1 },
{ CMD_DELAY_US, 0, 0, 0, 3, 0x0 },
{ CMD_DELAY_US, 0, 0, 0, 3, 0x0 },
{ CMD_DELAY_US, 0, 0, 0, 5, 0x0 }
};
int polaris_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state)
{
enum BACO_STATE cur_state;
smu7_baco_get_state(hwmgr, &cur_state);
if (cur_state == state)
/* aisc already in the target state */
return 0;
if (state == BACO_STATE_IN) {
baco_program_registers(hwmgr, gpio_tbl, ARRAY_SIZE(gpio_tbl));
baco_program_registers(hwmgr, enable_fb_req_rej_tbl,
ARRAY_SIZE(enable_fb_req_rej_tbl));
if (hwmgr->chip_id == CHIP_VEGAM) {
baco_program_registers(hwmgr, use_bclk_tbl_vg, ARRAY_SIZE(use_bclk_tbl_vg));
baco_program_registers(hwmgr, turn_off_plls_tbl_vg,
ARRAY_SIZE(turn_off_plls_tbl_vg));
} else {
baco_program_registers(hwmgr, use_bclk_tbl, ARRAY_SIZE(use_bclk_tbl));
baco_program_registers(hwmgr, turn_off_plls_tbl,
ARRAY_SIZE(turn_off_plls_tbl));
}
baco_program_registers(hwmgr, clk_req_b_tbl, ARRAY_SIZE(clk_req_b_tbl));
if (baco_program_registers(hwmgr, enter_baco_tbl,
ARRAY_SIZE(enter_baco_tbl)))
return 0;
} else if (state == BACO_STATE_OUT) {
/* HW requires at least 20ms between regulator off and on */
msleep(20);
/* Execute Hardware BACO exit sequence */
if (baco_program_registers(hwmgr, exit_baco_tbl,
ARRAY_SIZE(exit_baco_tbl))) {
if (baco_program_registers(hwmgr, clean_baco_tbl,
ARRAY_SIZE(clean_baco_tbl)))
return 0;
}
}
return -EINVAL;
}

View File

@@ -0,0 +1,29 @@
/*
* Copyright 2019 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.
*
*/
#ifndef __POLARIS_BACO_H__
#define __POLARIS_BACO_H__
#include "smu7_baco.h"
extern int polaris_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,46 @@
/*
* Copyright 2015 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.
*
*/
#ifndef _PP_OVERDRIVER_H_
#define _PP_OVERDRIVER_H_
#include <linux/types.h>
#include <linux/kernel.h>
struct phm_fuses_default {
uint64_t key;
uint32_t VFT2_m1;
uint32_t VFT2_m2;
uint32_t VFT2_b;
uint32_t VFT1_m1;
uint32_t VFT1_m2;
uint32_t VFT1_b;
uint32_t VFT0_m1;
uint32_t VFT0_m2;
uint32_t VFT0_b;
};
extern int pp_override_get_default_fuse_value(uint64_t key,
struct phm_fuses_default *result);
#endif

View File

@@ -0,0 +1,296 @@
/*
* Copyright 2017 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/types.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include "pp_psm.h"
int psm_init_power_state_table(struct pp_hwmgr *hwmgr)
{
int result;
unsigned int i;
unsigned int table_entries;
struct pp_power_state *state;
int size;
if (hwmgr->hwmgr_func->get_num_of_pp_table_entries == NULL)
return 0;
if (hwmgr->hwmgr_func->get_power_state_size == NULL)
return 0;
hwmgr->num_ps = table_entries = hwmgr->hwmgr_func->get_num_of_pp_table_entries(hwmgr);
hwmgr->ps_size = size = hwmgr->hwmgr_func->get_power_state_size(hwmgr) +
sizeof(struct pp_power_state);
if (table_entries == 0 || size == 0) {
pr_warn("Please check whether power state management is supported on this asic\n");
return 0;
}
hwmgr->ps = kcalloc(table_entries, size, GFP_KERNEL);
if (hwmgr->ps == NULL)
return -ENOMEM;
hwmgr->request_ps = kzalloc(size, GFP_KERNEL);
if (hwmgr->request_ps == NULL) {
kfree(hwmgr->ps);
hwmgr->ps = NULL;
return -ENOMEM;
}
hwmgr->current_ps = kzalloc(size, GFP_KERNEL);
if (hwmgr->current_ps == NULL) {
kfree(hwmgr->request_ps);
kfree(hwmgr->ps);
hwmgr->request_ps = NULL;
hwmgr->ps = NULL;
return -ENOMEM;
}
state = hwmgr->ps;
for (i = 0; i < table_entries; i++) {
result = hwmgr->hwmgr_func->get_pp_table_entry(hwmgr, i, state);
if (state->classification.flags & PP_StateClassificationFlag_Boot) {
hwmgr->boot_ps = state;
memcpy(hwmgr->current_ps, state, size);
memcpy(hwmgr->request_ps, state, size);
}
state->id = i + 1; /* assigned unique num for every power state id */
if (state->classification.flags & PP_StateClassificationFlag_Uvd)
hwmgr->uvd_ps = state;
state = (struct pp_power_state *)((unsigned long)state + size);
}
return 0;
}
int psm_fini_power_state_table(struct pp_hwmgr *hwmgr)
{
if (hwmgr == NULL)
return -EINVAL;
if (!hwmgr->ps)
return 0;
kfree(hwmgr->current_ps);
kfree(hwmgr->request_ps);
kfree(hwmgr->ps);
hwmgr->request_ps = NULL;
hwmgr->ps = NULL;
hwmgr->current_ps = NULL;
return 0;
}
static int psm_get_ui_state(struct pp_hwmgr *hwmgr,
enum PP_StateUILabel ui_label,
unsigned long *state_id)
{
struct pp_power_state *state;
int table_entries;
int i;
table_entries = hwmgr->num_ps;
state = hwmgr->ps;
for (i = 0; i < table_entries; i++) {
if (state->classification.ui_label & ui_label) {
*state_id = state->id;
return 0;
}
state = (struct pp_power_state *)((unsigned long)state + hwmgr->ps_size);
}
return -EINVAL;
}
static int psm_get_state_by_classification(struct pp_hwmgr *hwmgr,
enum PP_StateClassificationFlag flag,
unsigned long *state_id)
{
struct pp_power_state *state;
int table_entries;
int i;
table_entries = hwmgr->num_ps;
state = hwmgr->ps;
for (i = 0; i < table_entries; i++) {
if (state->classification.flags & flag) {
*state_id = state->id;
return 0;
}
state = (struct pp_power_state *)((unsigned long)state + hwmgr->ps_size);
}
return -EINVAL;
}
static int psm_set_states(struct pp_hwmgr *hwmgr, unsigned long state_id)
{
struct pp_power_state *state;
int table_entries;
int i;
table_entries = hwmgr->num_ps;
state = hwmgr->ps;
for (i = 0; i < table_entries; i++) {
if (state->id == state_id) {
memcpy(hwmgr->request_ps, state, hwmgr->ps_size);
return 0;
}
state = (struct pp_power_state *)((unsigned long)state + hwmgr->ps_size);
}
return -EINVAL;
}
int psm_set_boot_states(struct pp_hwmgr *hwmgr)
{
unsigned long state_id;
int ret = -EINVAL;
if (!hwmgr->ps)
return 0;
if (!psm_get_state_by_classification(hwmgr, PP_StateClassificationFlag_Boot,
&state_id))
ret = psm_set_states(hwmgr, state_id);
return ret;
}
int psm_set_performance_states(struct pp_hwmgr *hwmgr)
{
unsigned long state_id;
int ret = -EINVAL;
if (!hwmgr->ps)
return 0;
if (!psm_get_ui_state(hwmgr, PP_StateUILabel_Performance,
&state_id))
ret = psm_set_states(hwmgr, state_id);
return ret;
}
int psm_set_user_performance_state(struct pp_hwmgr *hwmgr,
enum PP_StateUILabel label_id,
struct pp_power_state **state)
{
int table_entries;
int i;
if (!hwmgr->ps)
return 0;
table_entries = hwmgr->num_ps;
*state = hwmgr->ps;
restart_search:
for (i = 0; i < table_entries; i++) {
if ((*state)->classification.ui_label & label_id)
return 0;
*state = (struct pp_power_state *)((uintptr_t)*state + hwmgr->ps_size);
}
switch (label_id) {
case PP_StateUILabel_Battery:
case PP_StateUILabel_Balanced:
label_id = PP_StateUILabel_Performance;
goto restart_search;
default:
break;
}
return -EINVAL;
}
static void power_state_management(struct pp_hwmgr *hwmgr,
struct pp_power_state *new_ps)
{
struct pp_power_state *pcurrent;
struct pp_power_state *requested;
bool equal;
if (new_ps != NULL)
requested = new_ps;
else
requested = hwmgr->request_ps;
pcurrent = hwmgr->current_ps;
phm_apply_state_adjust_rules(hwmgr, requested, pcurrent);
if (pcurrent == NULL || (0 != phm_check_states_equal(hwmgr,
&pcurrent->hardware, &requested->hardware, &equal)))
equal = false;
if (!equal || phm_check_smc_update_required_for_display_configuration(hwmgr)) {
phm_set_power_state(hwmgr, &pcurrent->hardware, &requested->hardware);
memcpy(hwmgr->current_ps, hwmgr->request_ps, hwmgr->ps_size);
}
}
int psm_adjust_power_state_dynamic(struct pp_hwmgr *hwmgr, bool skip_display_settings,
struct pp_power_state *new_ps)
{
uint32_t index;
long workload;
if (hwmgr->not_vf) {
if (!skip_display_settings)
phm_display_configuration_changed(hwmgr);
if (hwmgr->ps)
power_state_management(hwmgr, new_ps);
else
/*
* for vega12/vega20 which does not support power state manager
* DAL clock limits should also be honoured
*/
phm_apply_clock_adjust_rules(hwmgr);
if (!skip_display_settings)
phm_notify_smc_display_config_after_ps_adjustment(hwmgr);
}
if (!phm_force_dpm_levels(hwmgr, hwmgr->request_dpm_level))
hwmgr->dpm_level = hwmgr->request_dpm_level;
if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) {
index = fls(hwmgr->workload_mask);
index = index > 0 && index <= Workload_Policy_Max ? index - 1 : 0;
workload = hwmgr->workload_setting[index];
if (hwmgr->power_profile_mode != workload && hwmgr->hwmgr_func->set_power_profile_mode)
hwmgr->hwmgr_func->set_power_profile_mode(hwmgr, &workload, 0);
}
return 0;
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright 2017 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.
*
*/
#ifndef PP_PSM_H
#define PP_PSM_H
#include "hwmgr.h"
int psm_init_power_state_table(struct pp_hwmgr *hwmgr);
int psm_fini_power_state_table(struct pp_hwmgr *hwmgr);
int psm_set_boot_states(struct pp_hwmgr *hwmgr);
int psm_set_performance_states(struct pp_hwmgr *hwmgr);
int psm_set_user_performance_state(struct pp_hwmgr *hwmgr,
enum PP_StateUILabel label_id,
struct pp_power_state **state);
int psm_adjust_power_state_dynamic(struct pp_hwmgr *hwmgr,
bool skip_display_settings,
struct pp_power_state *new_ps);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,328 @@
/*
* Copyright 2015 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.
*
*/
#ifndef PP_ATOMVOLTAGECTRL_H
#define PP_ATOMVOLTAGECTRL_H
#include "hwmgr.h"
/* As returned from PowerConnectorDetectionTable. */
#define PP_ATOM_POWER_BUDGET_DISABLE_OVERDRIVE 0x80
#define PP_ATOM_POWER_BUDGET_SHOW_WARNING 0x40
#define PP_ATOM_POWER_BUDGET_SHOW_WAIVER 0x20
#define PP_ATOM_POWER_POWER_BUDGET_BEHAVIOUR 0x0F
/* New functions for Evergreen and beyond. */
#define PP_ATOMCTRL_MAX_VOLTAGE_ENTRIES 32
struct pp_atomctrl_clock_dividers {
uint32_t pll_post_divider;
uint32_t pll_feedback_divider;
uint32_t pll_ref_divider;
bool enable_post_divider;
};
typedef struct pp_atomctrl_clock_dividers pp_atomctrl_clock_dividers;
union pp_atomctrl_tcipll_fb_divider {
struct {
uint32_t ul_fb_div_frac : 14;
uint32_t ul_fb_div : 12;
uint32_t un_used : 6;
};
uint32_t ul_fb_divider;
};
typedef union pp_atomctrl_tcipll_fb_divider pp_atomctrl_tcipll_fb_divider;
struct pp_atomctrl_clock_dividers_rv730 {
uint32_t pll_post_divider;
pp_atomctrl_tcipll_fb_divider mpll_feedback_divider;
uint32_t pll_ref_divider;
bool enable_post_divider;
bool enable_dithen;
uint32_t vco_mode;
};
typedef struct pp_atomctrl_clock_dividers_rv730 pp_atomctrl_clock_dividers_rv730;
struct pp_atomctrl_clock_dividers_kong {
uint32_t pll_post_divider;
uint32_t real_clock;
};
typedef struct pp_atomctrl_clock_dividers_kong pp_atomctrl_clock_dividers_kong;
struct pp_atomctrl_clock_dividers_ci {
uint32_t pll_post_divider; /* post divider value */
uint32_t real_clock;
pp_atomctrl_tcipll_fb_divider ul_fb_div; /* Output Parameter: PLL FB divider */
uint8_t uc_pll_ref_div; /* Output Parameter: PLL ref divider */
uint8_t uc_pll_post_div; /* Output Parameter: PLL post divider */
uint8_t uc_pll_cntl_flag; /*Output Flags: control flag */
};
typedef struct pp_atomctrl_clock_dividers_ci pp_atomctrl_clock_dividers_ci;
struct pp_atomctrl_clock_dividers_vi {
uint32_t pll_post_divider; /* post divider value */
uint32_t real_clock;
pp_atomctrl_tcipll_fb_divider ul_fb_div; /*Output Parameter: PLL FB divider */
uint8_t uc_pll_ref_div; /*Output Parameter: PLL ref divider */
uint8_t uc_pll_post_div; /*Output Parameter: PLL post divider */
uint8_t uc_pll_cntl_flag; /*Output Flags: control flag */
};
typedef struct pp_atomctrl_clock_dividers_vi pp_atomctrl_clock_dividers_vi;
struct pp_atomctrl_clock_dividers_ai {
u16 usSclk_fcw_frac;
u16 usSclk_fcw_int;
u8 ucSclkPostDiv;
u8 ucSclkVcoMode;
u8 ucSclkPllRange;
u8 ucSscEnable;
u16 usSsc_fcw1_frac;
u16 usSsc_fcw1_int;
u16 usReserved;
u16 usPcc_fcw_int;
u16 usSsc_fcw_slew_frac;
u16 usPcc_fcw_slew_frac;
};
typedef struct pp_atomctrl_clock_dividers_ai pp_atomctrl_clock_dividers_ai;
union pp_atomctrl_s_mpll_fb_divider {
struct {
uint32_t cl_kf : 12;
uint32_t clk_frac : 12;
uint32_t un_used : 8;
};
uint32_t ul_fb_divider;
};
typedef union pp_atomctrl_s_mpll_fb_divider pp_atomctrl_s_mpll_fb_divider;
enum pp_atomctrl_spread_spectrum_mode {
pp_atomctrl_spread_spectrum_mode_down = 0,
pp_atomctrl_spread_spectrum_mode_center
};
typedef enum pp_atomctrl_spread_spectrum_mode pp_atomctrl_spread_spectrum_mode;
struct pp_atomctrl_memory_clock_param {
pp_atomctrl_s_mpll_fb_divider mpll_fb_divider;
uint32_t mpll_post_divider;
uint32_t bw_ctrl;
uint32_t dll_speed;
uint32_t vco_mode;
uint32_t yclk_sel;
uint32_t qdr;
uint32_t half_rate;
};
typedef struct pp_atomctrl_memory_clock_param pp_atomctrl_memory_clock_param;
struct pp_atomctrl_memory_clock_param_ai {
uint32_t ulClock;
uint32_t ulPostDiv;
uint16_t ulMclk_fcw_frac;
uint16_t ulMclk_fcw_int;
};
typedef struct pp_atomctrl_memory_clock_param_ai pp_atomctrl_memory_clock_param_ai;
struct pp_atomctrl_internal_ss_info {
uint32_t speed_spectrum_percentage; /* in 1/100 percentage */
uint32_t speed_spectrum_rate; /* in KHz */
pp_atomctrl_spread_spectrum_mode speed_spectrum_mode;
};
typedef struct pp_atomctrl_internal_ss_info pp_atomctrl_internal_ss_info;
#ifndef NUMBER_OF_M3ARB_PARAMS
#define NUMBER_OF_M3ARB_PARAMS 3
#endif
#ifndef NUMBER_OF_M3ARB_PARAM_SETS
#define NUMBER_OF_M3ARB_PARAM_SETS 10
#endif
struct pp_atomctrl_kong_system_info {
uint32_t ul_bootup_uma_clock; /* in 10kHz unit */
uint16_t us_max_nb_voltage; /* high NB voltage, calculated using current VDDNB (D24F2xDC) and VDDNB offset fuse; */
uint16_t us_min_nb_voltage; /* low NB voltage, calculated using current VDDNB (D24F2xDC) and VDDNB offset fuse; */
uint16_t us_bootup_nb_voltage; /* boot up NB voltage */
uint8_t uc_htc_tmp_lmt; /* bit [22:16] of D24F3x64 Hardware Thermal Control (HTC) Register, may not be needed, TBD */
uint8_t uc_tj_offset; /* bit [28:22] of D24F3xE4 Thermtrip Status Register,may not be needed, TBD */
/* 0: default 1: uvd 2: fs-3d */
uint32_t ul_csr_m3_srb_cntl[NUMBER_OF_M3ARB_PARAM_SETS][NUMBER_OF_M3ARB_PARAMS];/* arrays with values for CSR M3 arbiter for default */
};
typedef struct pp_atomctrl_kong_system_info pp_atomctrl_kong_system_info;
struct pp_atomctrl_memory_info {
uint8_t memory_vendor;
uint8_t memory_type;
};
typedef struct pp_atomctrl_memory_info pp_atomctrl_memory_info;
#define MAX_AC_TIMING_ENTRIES 16
struct pp_atomctrl_memory_clock_range_table {
uint8_t num_entries;
uint8_t rsv[3];
uint32_t mclk[MAX_AC_TIMING_ENTRIES];
};
typedef struct pp_atomctrl_memory_clock_range_table pp_atomctrl_memory_clock_range_table;
struct pp_atomctrl_voltage_table_entry {
uint16_t value;
uint32_t smio_low;
};
typedef struct pp_atomctrl_voltage_table_entry pp_atomctrl_voltage_table_entry;
struct pp_atomctrl_voltage_table {
uint32_t count;
uint32_t mask_low;
uint32_t phase_delay; /* Used for ATOM_GPIO_VOLTAGE_OBJECT_V3 and later */
pp_atomctrl_voltage_table_entry entries[PP_ATOMCTRL_MAX_VOLTAGE_ENTRIES];
};
typedef struct pp_atomctrl_voltage_table pp_atomctrl_voltage_table;
#define VBIOS_MC_REGISTER_ARRAY_SIZE 32
#define VBIOS_MAX_AC_TIMING_ENTRIES 20
struct pp_atomctrl_mc_reg_entry {
uint32_t mclk_max;
uint32_t mc_data[VBIOS_MC_REGISTER_ARRAY_SIZE];
};
typedef struct pp_atomctrl_mc_reg_entry pp_atomctrl_mc_reg_entry;
struct pp_atomctrl_mc_register_address {
uint16_t s1;
uint8_t uc_pre_reg_data;
};
typedef struct pp_atomctrl_mc_register_address pp_atomctrl_mc_register_address;
#define MAX_SCLK_RANGE 8
struct pp_atom_ctrl_sclk_range_table_entry{
uint8_t ucVco_setting;
uint8_t ucPostdiv;
uint16_t usFcw_pcc;
uint16_t usFcw_trans_upper;
uint16_t usRcw_trans_lower;
};
struct pp_atom_ctrl_sclk_range_table{
struct pp_atom_ctrl_sclk_range_table_entry entry[MAX_SCLK_RANGE];
};
struct pp_atomctrl_mc_reg_table {
uint8_t last; /* number of registers */
uint8_t num_entries; /* number of AC timing entries */
pp_atomctrl_mc_reg_entry mc_reg_table_entry[VBIOS_MAX_AC_TIMING_ENTRIES];
pp_atomctrl_mc_register_address mc_reg_address[VBIOS_MC_REGISTER_ARRAY_SIZE];
};
typedef struct pp_atomctrl_mc_reg_table pp_atomctrl_mc_reg_table;
struct pp_atomctrl_gpio_pin_assignment {
uint16_t us_gpio_pin_aindex;
uint8_t uc_gpio_pin_bit_shift;
};
typedef struct pp_atomctrl_gpio_pin_assignment pp_atomctrl_gpio_pin_assignment;
struct pp_atom_ctrl__avfs_parameters {
uint32_t ulAVFS_meanNsigma_Acontant0;
uint32_t ulAVFS_meanNsigma_Acontant1;
uint32_t ulAVFS_meanNsigma_Acontant2;
uint16_t usAVFS_meanNsigma_DC_tol_sigma;
uint16_t usAVFS_meanNsigma_Platform_mean;
uint16_t usAVFS_meanNsigma_Platform_sigma;
uint32_t ulGB_VDROOP_TABLE_CKSOFF_a0;
uint32_t ulGB_VDROOP_TABLE_CKSOFF_a1;
uint32_t ulGB_VDROOP_TABLE_CKSOFF_a2;
uint32_t ulGB_VDROOP_TABLE_CKSON_a0;
uint32_t ulGB_VDROOP_TABLE_CKSON_a1;
uint32_t ulGB_VDROOP_TABLE_CKSON_a2;
uint32_t ulAVFSGB_FUSE_TABLE_CKSOFF_m1;
uint16_t usAVFSGB_FUSE_TABLE_CKSOFF_m2;
uint32_t ulAVFSGB_FUSE_TABLE_CKSOFF_b;
uint32_t ulAVFSGB_FUSE_TABLE_CKSON_m1;
uint16_t usAVFSGB_FUSE_TABLE_CKSON_m2;
uint32_t ulAVFSGB_FUSE_TABLE_CKSON_b;
uint16_t usMaxVoltage_0_25mv;
uint8_t ucEnableGB_VDROOP_TABLE_CKSOFF;
uint8_t ucEnableGB_VDROOP_TABLE_CKSON;
uint8_t ucEnableGB_FUSE_TABLE_CKSOFF;
uint8_t ucEnableGB_FUSE_TABLE_CKSON;
uint16_t usPSM_Age_ComFactor;
uint8_t ucEnableApplyAVFS_CKS_OFF_Voltage;
uint8_t ucReserved;
};
extern bool atomctrl_get_pp_assign_pin(struct pp_hwmgr *hwmgr, const uint32_t pinId, pp_atomctrl_gpio_pin_assignment *gpio_pin_assignment);
extern int atomctrl_get_voltage_evv_on_sclk(struct pp_hwmgr *hwmgr, uint8_t voltage_type, uint32_t sclk, uint16_t virtual_voltage_Id, uint16_t *voltage);
extern int atomctrl_get_voltage_evv(struct pp_hwmgr *hwmgr, uint16_t virtual_voltage_id, uint16_t *voltage);
extern uint32_t atomctrl_get_mpll_reference_clock(struct pp_hwmgr *hwmgr);
extern int atomctrl_get_memory_clock_spread_spectrum(struct pp_hwmgr *hwmgr, const uint32_t memory_clock, pp_atomctrl_internal_ss_info *ssInfo);
extern int atomctrl_get_engine_clock_spread_spectrum(struct pp_hwmgr *hwmgr, const uint32_t engine_clock, pp_atomctrl_internal_ss_info *ssInfo);
extern int atomctrl_initialize_mc_reg_table(struct pp_hwmgr *hwmgr, uint8_t module_index, pp_atomctrl_mc_reg_table *table);
extern int atomctrl_set_engine_dram_timings_rv770(struct pp_hwmgr *hwmgr, uint32_t engine_clock, uint32_t memory_clock);
extern uint32_t atomctrl_get_reference_clock(struct pp_hwmgr *hwmgr);
extern int atomctrl_get_memory_pll_dividers_si(struct pp_hwmgr *hwmgr, uint32_t clock_value, pp_atomctrl_memory_clock_param *mpll_param, bool strobe_mode);
extern int atomctrl_get_engine_pll_dividers_vi(struct pp_hwmgr *hwmgr, uint32_t clock_value, pp_atomctrl_clock_dividers_vi *dividers);
extern int atomctrl_get_dfs_pll_dividers_vi(struct pp_hwmgr *hwmgr, uint32_t clock_value, pp_atomctrl_clock_dividers_vi *dividers);
extern bool atomctrl_is_voltage_controlled_by_gpio_v3(struct pp_hwmgr *hwmgr, uint8_t voltage_type, uint8_t voltage_mode);
extern int atomctrl_get_voltage_table_v3(struct pp_hwmgr *hwmgr, uint8_t voltage_type, uint8_t voltage_mode, pp_atomctrl_voltage_table *voltage_table);
extern int atomctrl_get_memory_pll_dividers_vi(struct pp_hwmgr *hwmgr,
uint32_t clock_value, pp_atomctrl_memory_clock_param *mpll_param);
extern int atomctrl_get_memory_pll_dividers_ai(struct pp_hwmgr *hwmgr,
uint32_t clock_value, pp_atomctrl_memory_clock_param_ai *mpll_param);
extern int atomctrl_get_engine_pll_dividers_kong(struct pp_hwmgr *hwmgr,
uint32_t clock_value,
pp_atomctrl_clock_dividers_kong *dividers);
extern int atomctrl_read_efuse(struct pp_hwmgr *hwmgr, uint16_t start_index,
uint16_t end_index, uint32_t mask, uint32_t *efuse);
extern int atomctrl_calculate_voltage_evv_on_sclk(struct pp_hwmgr *hwmgr, uint8_t voltage_type,
uint32_t sclk, uint16_t virtual_voltage_Id, uint16_t *voltage, uint16_t dpm_level, bool debug);
extern int atomctrl_get_engine_pll_dividers_ai(struct pp_hwmgr *hwmgr, uint32_t clock_value, pp_atomctrl_clock_dividers_ai *dividers);
extern int atomctrl_set_ac_timing_ai(struct pp_hwmgr *hwmgr, uint32_t memory_clock,
uint8_t level);
extern int atomctrl_get_voltage_evv_on_sclk_ai(struct pp_hwmgr *hwmgr, uint8_t voltage_type,
uint32_t sclk, uint16_t virtual_voltage_Id, uint32_t *voltage);
extern int atomctrl_get_smc_sclk_range_table(struct pp_hwmgr *hwmgr, struct pp_atom_ctrl_sclk_range_table *table);
extern int atomctrl_get_avfs_information(struct pp_hwmgr *hwmgr, struct pp_atom_ctrl__avfs_parameters *param);
extern int atomctrl_get_svi2_info(struct pp_hwmgr *hwmgr, uint8_t voltage_type,
uint8_t *svd_gpio_id, uint8_t *svc_gpio_id,
uint16_t *load_line);
extern int atomctrl_get_leakage_vddc_base_on_leakage(struct pp_hwmgr *hwmgr,
uint16_t *vddc, uint16_t *vddci,
uint16_t virtual_voltage_id,
uint16_t efuse_voltage_id);
extern int atomctrl_get_leakage_id_from_efuse(struct pp_hwmgr *hwmgr, uint16_t *virtual_voltage_id);
extern void atomctrl_get_voltage_range(struct pp_hwmgr *hwmgr, uint32_t *max_vddc,
uint32_t *min_vddc);
#endif

View File

@@ -0,0 +1,710 @@
/*
* 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 "ppatomfwctrl.h"
#include "atomfirmware.h"
#include "atom.h"
#include "pp_debug.h"
static const union atom_voltage_object_v4 *pp_atomfwctrl_lookup_voltage_type_v4(
const struct atom_voltage_objects_info_v4_1 *voltage_object_info_table,
uint8_t voltage_type, uint8_t voltage_mode)
{
unsigned int size = le16_to_cpu(
voltage_object_info_table->table_header.structuresize);
unsigned int offset =
offsetof(struct atom_voltage_objects_info_v4_1, voltage_object[0]);
unsigned long start = (unsigned long)voltage_object_info_table;
while (offset < size) {
const union atom_voltage_object_v4 *voltage_object =
(const union atom_voltage_object_v4 *)(start + offset);
if (voltage_type == voltage_object->gpio_voltage_obj.header.voltage_type &&
voltage_mode == voltage_object->gpio_voltage_obj.header.voltage_mode)
return voltage_object;
offset += le16_to_cpu(voltage_object->gpio_voltage_obj.header.object_size);
}
return NULL;
}
static struct atom_voltage_objects_info_v4_1 *pp_atomfwctrl_get_voltage_info_table(
struct pp_hwmgr *hwmgr)
{
const void *table_address;
uint16_t idx;
idx = GetIndexIntoMasterDataTable(voltageobject_info);
table_address = smu_atom_get_data_table(hwmgr->adev,
idx, NULL, NULL, NULL);
PP_ASSERT_WITH_CODE(table_address,
"Error retrieving BIOS Table Address!",
return NULL);
return (struct atom_voltage_objects_info_v4_1 *)table_address;
}
/**
* Returns TRUE if the given voltage type is controlled by GPIO pins.
* voltage_type is one of SET_VOLTAGE_TYPE_ASIC_VDDC, SET_VOLTAGE_TYPE_ASIC_MVDDC, SET_VOLTAGE_TYPE_ASIC_MVDDQ.
* voltage_mode is one of ATOM_SET_VOLTAGE, ATOM_SET_VOLTAGE_PHASE
*/
bool pp_atomfwctrl_is_voltage_controlled_by_gpio_v4(struct pp_hwmgr *hwmgr,
uint8_t voltage_type, uint8_t voltage_mode)
{
struct atom_voltage_objects_info_v4_1 *voltage_info =
(struct atom_voltage_objects_info_v4_1 *)
pp_atomfwctrl_get_voltage_info_table(hwmgr);
bool ret;
/* If we cannot find the table do NOT try to control this voltage. */
PP_ASSERT_WITH_CODE(voltage_info,
"Could not find Voltage Table in BIOS.",
return false);
ret = (pp_atomfwctrl_lookup_voltage_type_v4(voltage_info,
voltage_type, voltage_mode)) ? true : false;
return ret;
}
int pp_atomfwctrl_get_voltage_table_v4(struct pp_hwmgr *hwmgr,
uint8_t voltage_type, uint8_t voltage_mode,
struct pp_atomfwctrl_voltage_table *voltage_table)
{
struct atom_voltage_objects_info_v4_1 *voltage_info =
(struct atom_voltage_objects_info_v4_1 *)
pp_atomfwctrl_get_voltage_info_table(hwmgr);
const union atom_voltage_object_v4 *voltage_object;
unsigned int i;
int result = 0;
PP_ASSERT_WITH_CODE(voltage_info,
"Could not find Voltage Table in BIOS.",
return -1);
voltage_object = pp_atomfwctrl_lookup_voltage_type_v4(voltage_info,
voltage_type, voltage_mode);
if (!voltage_object)
return -1;
voltage_table->count = 0;
if (voltage_mode == VOLTAGE_OBJ_GPIO_LUT) {
PP_ASSERT_WITH_CODE(
(voltage_object->gpio_voltage_obj.gpio_entry_num <=
PP_ATOMFWCTRL_MAX_VOLTAGE_ENTRIES),
"Too many voltage entries!",
result = -1);
if (!result) {
for (i = 0; i < voltage_object->gpio_voltage_obj.
gpio_entry_num; i++) {
voltage_table->entries[i].value =
le16_to_cpu(voltage_object->gpio_voltage_obj.
voltage_gpio_lut[i].voltage_level_mv);
voltage_table->entries[i].smio_low =
le32_to_cpu(voltage_object->gpio_voltage_obj.
voltage_gpio_lut[i].voltage_gpio_reg_val);
}
voltage_table->count =
voltage_object->gpio_voltage_obj.gpio_entry_num;
voltage_table->mask_low =
le32_to_cpu(
voltage_object->gpio_voltage_obj.gpio_mask_val);
voltage_table->phase_delay =
voltage_object->gpio_voltage_obj.phase_delay_us;
}
} else if (voltage_mode == VOLTAGE_OBJ_SVID2) {
voltage_table->psi1_enable =
(voltage_object->svid2_voltage_obj.loadline_psi1 & 0x20) >> 5;
voltage_table->psi0_enable =
voltage_object->svid2_voltage_obj.psi0_enable & 0x1;
voltage_table->max_vid_step =
voltage_object->svid2_voltage_obj.maxvstep;
voltage_table->telemetry_offset =
voltage_object->svid2_voltage_obj.telemetry_offset;
voltage_table->telemetry_slope =
voltage_object->svid2_voltage_obj.telemetry_gain;
} else
PP_ASSERT_WITH_CODE(false,
"Unsupported Voltage Object Mode!",
result = -1);
return result;
}
static struct atom_gpio_pin_lut_v2_1 *pp_atomfwctrl_get_gpio_lookup_table(
struct pp_hwmgr *hwmgr)
{
const void *table_address;
uint16_t idx;
idx = GetIndexIntoMasterDataTable(gpio_pin_lut);
table_address = smu_atom_get_data_table(hwmgr->adev,
idx, NULL, NULL, NULL);
PP_ASSERT_WITH_CODE(table_address,
"Error retrieving BIOS Table Address!",
return NULL);
return (struct atom_gpio_pin_lut_v2_1 *)table_address;
}
static bool pp_atomfwctrl_lookup_gpio_pin(
struct atom_gpio_pin_lut_v2_1 *gpio_lookup_table,
const uint32_t pin_id,
struct pp_atomfwctrl_gpio_pin_assignment *gpio_pin_assignment)
{
unsigned int size = le16_to_cpu(
gpio_lookup_table->table_header.structuresize);
unsigned int offset =
offsetof(struct atom_gpio_pin_lut_v2_1, gpio_pin[0]);
unsigned long start = (unsigned long)gpio_lookup_table;
while (offset < size) {
const struct atom_gpio_pin_assignment *pin_assignment =
(const struct atom_gpio_pin_assignment *)(start + offset);
if (pin_id == pin_assignment->gpio_id) {
gpio_pin_assignment->uc_gpio_pin_bit_shift =
pin_assignment->gpio_bitshift;
gpio_pin_assignment->us_gpio_pin_aindex =
le16_to_cpu(pin_assignment->data_a_reg_index);
return true;
}
offset += offsetof(struct atom_gpio_pin_assignment, gpio_id) + 1;
}
return false;
}
/**
* Returns TRUE if the given pin id find in lookup table.
*/
bool pp_atomfwctrl_get_pp_assign_pin(struct pp_hwmgr *hwmgr,
const uint32_t pin_id,
struct pp_atomfwctrl_gpio_pin_assignment *gpio_pin_assignment)
{
bool ret = false;
struct atom_gpio_pin_lut_v2_1 *gpio_lookup_table =
pp_atomfwctrl_get_gpio_lookup_table(hwmgr);
/* If we cannot find the table do NOT try to control this voltage. */
PP_ASSERT_WITH_CODE(gpio_lookup_table,
"Could not find GPIO lookup Table in BIOS.",
return false);
ret = pp_atomfwctrl_lookup_gpio_pin(gpio_lookup_table,
pin_id, gpio_pin_assignment);
return ret;
}
/**
* Enter to SelfRefresh mode.
* @param hwmgr
*/
int pp_atomfwctrl_enter_self_refresh(struct pp_hwmgr *hwmgr)
{
/* 0 - no action
* 1 - leave power to video memory always on
*/
return 0;
}
/** pp_atomfwctrl_get_gpu_pll_dividers_vega10().
*
* @param hwmgr input parameter: pointer to HwMgr
* @param clock_type input parameter: Clock type: 1 - GFXCLK, 2 - UCLK, 0 - All other clocks
* @param clock_value input parameter: Clock
* @param dividers output parameter:Clock dividers
*/
int pp_atomfwctrl_get_gpu_pll_dividers_vega10(struct pp_hwmgr *hwmgr,
uint32_t clock_type, uint32_t clock_value,
struct pp_atomfwctrl_clock_dividers_soc15 *dividers)
{
struct amdgpu_device *adev = hwmgr->adev;
struct compute_gpu_clock_input_parameter_v1_8 pll_parameters;
struct compute_gpu_clock_output_parameter_v1_8 *pll_output;
uint32_t idx;
pll_parameters.gpuclock_10khz = (uint32_t)clock_value;
pll_parameters.gpu_clock_type = clock_type;
idx = GetIndexIntoMasterCmdTable(computegpuclockparam);
if (amdgpu_atom_execute_table(
adev->mode_info.atom_context, idx, (uint32_t *)&pll_parameters))
return -EINVAL;
pll_output = (struct compute_gpu_clock_output_parameter_v1_8 *)
&pll_parameters;
dividers->ulClock = le32_to_cpu(pll_output->gpuclock_10khz);
dividers->ulDid = le32_to_cpu(pll_output->dfs_did);
dividers->ulPll_fb_mult = le32_to_cpu(pll_output->pll_fb_mult);
dividers->ulPll_ss_fbsmult = le32_to_cpu(pll_output->pll_ss_fbsmult);
dividers->usPll_ss_slew_frac = le16_to_cpu(pll_output->pll_ss_slew_frac);
dividers->ucPll_ss_enable = pll_output->pll_ss_enable;
return 0;
}
int pp_atomfwctrl_get_avfs_information(struct pp_hwmgr *hwmgr,
struct pp_atomfwctrl_avfs_parameters *param)
{
uint16_t idx;
uint8_t format_revision, content_revision;
struct atom_asic_profiling_info_v4_1 *profile;
struct atom_asic_profiling_info_v4_2 *profile_v4_2;
idx = GetIndexIntoMasterDataTable(asic_profiling_info);
profile = (struct atom_asic_profiling_info_v4_1 *)
smu_atom_get_data_table(hwmgr->adev,
idx, NULL, NULL, NULL);
if (!profile)
return -1;
format_revision = ((struct atom_common_table_header *)profile)->format_revision;
content_revision = ((struct atom_common_table_header *)profile)->content_revision;
if (format_revision == 4 && content_revision == 1) {
param->ulMaxVddc = le32_to_cpu(profile->maxvddc);
param->ulMinVddc = le32_to_cpu(profile->minvddc);
param->ulMeanNsigmaAcontant0 =
le32_to_cpu(profile->avfs_meannsigma_acontant0);
param->ulMeanNsigmaAcontant1 =
le32_to_cpu(profile->avfs_meannsigma_acontant1);
param->ulMeanNsigmaAcontant2 =
le32_to_cpu(profile->avfs_meannsigma_acontant2);
param->usMeanNsigmaDcTolSigma =
le16_to_cpu(profile->avfs_meannsigma_dc_tol_sigma);
param->usMeanNsigmaPlatformMean =
le16_to_cpu(profile->avfs_meannsigma_platform_mean);
param->usMeanNsigmaPlatformSigma =
le16_to_cpu(profile->avfs_meannsigma_platform_sigma);
param->ulGbVdroopTableCksoffA0 =
le32_to_cpu(profile->gb_vdroop_table_cksoff_a0);
param->ulGbVdroopTableCksoffA1 =
le32_to_cpu(profile->gb_vdroop_table_cksoff_a1);
param->ulGbVdroopTableCksoffA2 =
le32_to_cpu(profile->gb_vdroop_table_cksoff_a2);
param->ulGbVdroopTableCksonA0 =
le32_to_cpu(profile->gb_vdroop_table_ckson_a0);
param->ulGbVdroopTableCksonA1 =
le32_to_cpu(profile->gb_vdroop_table_ckson_a1);
param->ulGbVdroopTableCksonA2 =
le32_to_cpu(profile->gb_vdroop_table_ckson_a2);
param->ulGbFuseTableCksoffM1 =
le32_to_cpu(profile->avfsgb_fuse_table_cksoff_m1);
param->ulGbFuseTableCksoffM2 =
le32_to_cpu(profile->avfsgb_fuse_table_cksoff_m2);
param->ulGbFuseTableCksoffB =
le32_to_cpu(profile->avfsgb_fuse_table_cksoff_b);
param->ulGbFuseTableCksonM1 =
le32_to_cpu(profile->avfsgb_fuse_table_ckson_m1);
param->ulGbFuseTableCksonM2 =
le32_to_cpu(profile->avfsgb_fuse_table_ckson_m2);
param->ulGbFuseTableCksonB =
le32_to_cpu(profile->avfsgb_fuse_table_ckson_b);
param->ucEnableGbVdroopTableCkson =
profile->enable_gb_vdroop_table_ckson;
param->ucEnableGbFuseTableCkson =
profile->enable_gb_fuse_table_ckson;
param->usPsmAgeComfactor =
le16_to_cpu(profile->psm_age_comfactor);
param->ulDispclk2GfxclkM1 =
le32_to_cpu(profile->dispclk2gfxclk_a);
param->ulDispclk2GfxclkM2 =
le32_to_cpu(profile->dispclk2gfxclk_b);
param->ulDispclk2GfxclkB =
le32_to_cpu(profile->dispclk2gfxclk_c);
param->ulDcefclk2GfxclkM1 =
le32_to_cpu(profile->dcefclk2gfxclk_a);
param->ulDcefclk2GfxclkM2 =
le32_to_cpu(profile->dcefclk2gfxclk_b);
param->ulDcefclk2GfxclkB =
le32_to_cpu(profile->dcefclk2gfxclk_c);
param->ulPixelclk2GfxclkM1 =
le32_to_cpu(profile->pixclk2gfxclk_a);
param->ulPixelclk2GfxclkM2 =
le32_to_cpu(profile->pixclk2gfxclk_b);
param->ulPixelclk2GfxclkB =
le32_to_cpu(profile->pixclk2gfxclk_c);
param->ulPhyclk2GfxclkM1 =
le32_to_cpu(profile->phyclk2gfxclk_a);
param->ulPhyclk2GfxclkM2 =
le32_to_cpu(profile->phyclk2gfxclk_b);
param->ulPhyclk2GfxclkB =
le32_to_cpu(profile->phyclk2gfxclk_c);
param->ulAcgGbVdroopTableA0 = 0;
param->ulAcgGbVdroopTableA1 = 0;
param->ulAcgGbVdroopTableA2 = 0;
param->ulAcgGbFuseTableM1 = 0;
param->ulAcgGbFuseTableM2 = 0;
param->ulAcgGbFuseTableB = 0;
param->ucAcgEnableGbVdroopTable = 0;
param->ucAcgEnableGbFuseTable = 0;
} else if (format_revision == 4 && content_revision == 2) {
profile_v4_2 = (struct atom_asic_profiling_info_v4_2 *)profile;
param->ulMaxVddc = le32_to_cpu(profile_v4_2->maxvddc);
param->ulMinVddc = le32_to_cpu(profile_v4_2->minvddc);
param->ulMeanNsigmaAcontant0 =
le32_to_cpu(profile_v4_2->avfs_meannsigma_acontant0);
param->ulMeanNsigmaAcontant1 =
le32_to_cpu(profile_v4_2->avfs_meannsigma_acontant1);
param->ulMeanNsigmaAcontant2 =
le32_to_cpu(profile_v4_2->avfs_meannsigma_acontant2);
param->usMeanNsigmaDcTolSigma =
le16_to_cpu(profile_v4_2->avfs_meannsigma_dc_tol_sigma);
param->usMeanNsigmaPlatformMean =
le16_to_cpu(profile_v4_2->avfs_meannsigma_platform_mean);
param->usMeanNsigmaPlatformSigma =
le16_to_cpu(profile_v4_2->avfs_meannsigma_platform_sigma);
param->ulGbVdroopTableCksoffA0 =
le32_to_cpu(profile_v4_2->gb_vdroop_table_cksoff_a0);
param->ulGbVdroopTableCksoffA1 =
le32_to_cpu(profile_v4_2->gb_vdroop_table_cksoff_a1);
param->ulGbVdroopTableCksoffA2 =
le32_to_cpu(profile_v4_2->gb_vdroop_table_cksoff_a2);
param->ulGbVdroopTableCksonA0 =
le32_to_cpu(profile_v4_2->gb_vdroop_table_ckson_a0);
param->ulGbVdroopTableCksonA1 =
le32_to_cpu(profile_v4_2->gb_vdroop_table_ckson_a1);
param->ulGbVdroopTableCksonA2 =
le32_to_cpu(profile_v4_2->gb_vdroop_table_ckson_a2);
param->ulGbFuseTableCksoffM1 =
le32_to_cpu(profile_v4_2->avfsgb_fuse_table_cksoff_m1);
param->ulGbFuseTableCksoffM2 =
le32_to_cpu(profile_v4_2->avfsgb_fuse_table_cksoff_m2);
param->ulGbFuseTableCksoffB =
le32_to_cpu(profile_v4_2->avfsgb_fuse_table_cksoff_b);
param->ulGbFuseTableCksonM1 =
le32_to_cpu(profile_v4_2->avfsgb_fuse_table_ckson_m1);
param->ulGbFuseTableCksonM2 =
le32_to_cpu(profile_v4_2->avfsgb_fuse_table_ckson_m2);
param->ulGbFuseTableCksonB =
le32_to_cpu(profile_v4_2->avfsgb_fuse_table_ckson_b);
param->ucEnableGbVdroopTableCkson =
profile_v4_2->enable_gb_vdroop_table_ckson;
param->ucEnableGbFuseTableCkson =
profile_v4_2->enable_gb_fuse_table_ckson;
param->usPsmAgeComfactor =
le16_to_cpu(profile_v4_2->psm_age_comfactor);
param->ulDispclk2GfxclkM1 =
le32_to_cpu(profile_v4_2->dispclk2gfxclk_a);
param->ulDispclk2GfxclkM2 =
le32_to_cpu(profile_v4_2->dispclk2gfxclk_b);
param->ulDispclk2GfxclkB =
le32_to_cpu(profile_v4_2->dispclk2gfxclk_c);
param->ulDcefclk2GfxclkM1 =
le32_to_cpu(profile_v4_2->dcefclk2gfxclk_a);
param->ulDcefclk2GfxclkM2 =
le32_to_cpu(profile_v4_2->dcefclk2gfxclk_b);
param->ulDcefclk2GfxclkB =
le32_to_cpu(profile_v4_2->dcefclk2gfxclk_c);
param->ulPixelclk2GfxclkM1 =
le32_to_cpu(profile_v4_2->pixclk2gfxclk_a);
param->ulPixelclk2GfxclkM2 =
le32_to_cpu(profile_v4_2->pixclk2gfxclk_b);
param->ulPixelclk2GfxclkB =
le32_to_cpu(profile_v4_2->pixclk2gfxclk_c);
param->ulPhyclk2GfxclkM1 =
le32_to_cpu(profile->phyclk2gfxclk_a);
param->ulPhyclk2GfxclkM2 =
le32_to_cpu(profile_v4_2->phyclk2gfxclk_b);
param->ulPhyclk2GfxclkB =
le32_to_cpu(profile_v4_2->phyclk2gfxclk_c);
param->ulAcgGbVdroopTableA0 = le32_to_cpu(profile_v4_2->acg_gb_vdroop_table_a0);
param->ulAcgGbVdroopTableA1 = le32_to_cpu(profile_v4_2->acg_gb_vdroop_table_a1);
param->ulAcgGbVdroopTableA2 = le32_to_cpu(profile_v4_2->acg_gb_vdroop_table_a2);
param->ulAcgGbFuseTableM1 = le32_to_cpu(profile_v4_2->acg_avfsgb_fuse_table_m1);
param->ulAcgGbFuseTableM2 = le32_to_cpu(profile_v4_2->acg_avfsgb_fuse_table_m2);
param->ulAcgGbFuseTableB = le32_to_cpu(profile_v4_2->acg_avfsgb_fuse_table_b);
param->ucAcgEnableGbVdroopTable = le32_to_cpu(profile_v4_2->enable_acg_gb_vdroop_table);
param->ucAcgEnableGbFuseTable = le32_to_cpu(profile_v4_2->enable_acg_gb_fuse_table);
} else {
pr_info("Invalid VBIOS AVFS ProfilingInfo Revision!\n");
return -EINVAL;
}
return 0;
}
int pp_atomfwctrl_get_gpio_information(struct pp_hwmgr *hwmgr,
struct pp_atomfwctrl_gpio_parameters *param)
{
struct atom_smu_info_v3_1 *info;
uint16_t idx;
idx = GetIndexIntoMasterDataTable(smu_info);
info = (struct atom_smu_info_v3_1 *)
smu_atom_get_data_table(hwmgr->adev,
idx, NULL, NULL, NULL);
if (!info) {
pr_info("Error retrieving BIOS smu_info Table Address!");
return -1;
}
param->ucAcDcGpio = info->ac_dc_gpio_bit;
param->ucAcDcPolarity = info->ac_dc_polarity;
param->ucVR0HotGpio = info->vr0hot_gpio_bit;
param->ucVR0HotPolarity = info->vr0hot_polarity;
param->ucVR1HotGpio = info->vr1hot_gpio_bit;
param->ucVR1HotPolarity = info->vr1hot_polarity;
param->ucFwCtfGpio = info->fw_ctf_gpio_bit;
param->ucFwCtfPolarity = info->fw_ctf_polarity;
return 0;
}
int pp_atomfwctrl_get_clk_information_by_clkid(struct pp_hwmgr *hwmgr,
uint8_t clk_id, uint8_t syspll_id,
uint32_t *frequency)
{
struct amdgpu_device *adev = hwmgr->adev;
struct atom_get_smu_clock_info_parameters_v3_1 parameters;
struct atom_get_smu_clock_info_output_parameters_v3_1 *output;
uint32_t ix;
parameters.clk_id = clk_id;
parameters.syspll_id = syspll_id;
parameters.command = GET_SMU_CLOCK_INFO_V3_1_GET_CLOCK_FREQ;
parameters.dfsdid = 0;
ix = GetIndexIntoMasterCmdTable(getsmuclockinfo);
if (amdgpu_atom_execute_table(
adev->mode_info.atom_context, ix, (uint32_t *)&parameters))
return -EINVAL;
output = (struct atom_get_smu_clock_info_output_parameters_v3_1 *)&parameters;
*frequency = le32_to_cpu(output->atom_smu_outputclkfreq.smu_clock_freq_hz) / 10000;
return 0;
}
static void pp_atomfwctrl_copy_vbios_bootup_values_3_2(struct pp_hwmgr *hwmgr,
struct pp_atomfwctrl_bios_boot_up_values *boot_values,
struct atom_firmware_info_v3_2 *fw_info)
{
uint32_t frequency = 0;
boot_values->ulRevision = fw_info->firmware_revision;
boot_values->ulGfxClk = fw_info->bootup_sclk_in10khz;
boot_values->ulUClk = fw_info->bootup_mclk_in10khz;
boot_values->usVddc = fw_info->bootup_vddc_mv;
boot_values->usVddci = fw_info->bootup_vddci_mv;
boot_values->usMvddc = fw_info->bootup_mvddc_mv;
boot_values->usVddGfx = fw_info->bootup_vddgfx_mv;
boot_values->ucCoolingID = fw_info->coolingsolution_id;
boot_values->ulSocClk = 0;
boot_values->ulDCEFClk = 0;
if (!pp_atomfwctrl_get_clk_information_by_clkid(hwmgr, SMU11_SYSPLL0_SOCCLK_ID, SMU11_SYSPLL0_ID, &frequency))
boot_values->ulSocClk = frequency;
if (!pp_atomfwctrl_get_clk_information_by_clkid(hwmgr, SMU11_SYSPLL0_DCEFCLK_ID, SMU11_SYSPLL0_ID, &frequency))
boot_values->ulDCEFClk = frequency;
if (!pp_atomfwctrl_get_clk_information_by_clkid(hwmgr, SMU11_SYSPLL0_ECLK_ID, SMU11_SYSPLL0_ID, &frequency))
boot_values->ulEClk = frequency;
if (!pp_atomfwctrl_get_clk_information_by_clkid(hwmgr, SMU11_SYSPLL0_VCLK_ID, SMU11_SYSPLL0_ID, &frequency))
boot_values->ulVClk = frequency;
if (!pp_atomfwctrl_get_clk_information_by_clkid(hwmgr, SMU11_SYSPLL0_DCLK_ID, SMU11_SYSPLL0_ID, &frequency))
boot_values->ulDClk = frequency;
if (!pp_atomfwctrl_get_clk_information_by_clkid(hwmgr, SMU11_SYSPLL1_0_FCLK_ID, SMU11_SYSPLL1_2_ID, &frequency))
boot_values->ulFClk = frequency;
}
static void pp_atomfwctrl_copy_vbios_bootup_values_3_1(struct pp_hwmgr *hwmgr,
struct pp_atomfwctrl_bios_boot_up_values *boot_values,
struct atom_firmware_info_v3_1 *fw_info)
{
uint32_t frequency = 0;
boot_values->ulRevision = fw_info->firmware_revision;
boot_values->ulGfxClk = fw_info->bootup_sclk_in10khz;
boot_values->ulUClk = fw_info->bootup_mclk_in10khz;
boot_values->usVddc = fw_info->bootup_vddc_mv;
boot_values->usVddci = fw_info->bootup_vddci_mv;
boot_values->usMvddc = fw_info->bootup_mvddc_mv;
boot_values->usVddGfx = fw_info->bootup_vddgfx_mv;
boot_values->ucCoolingID = fw_info->coolingsolution_id;
boot_values->ulSocClk = 0;
boot_values->ulDCEFClk = 0;
if (!pp_atomfwctrl_get_clk_information_by_clkid(hwmgr, SMU9_SYSPLL0_SOCCLK_ID, 0, &frequency))
boot_values->ulSocClk = frequency;
if (!pp_atomfwctrl_get_clk_information_by_clkid(hwmgr, SMU9_SYSPLL0_DCEFCLK_ID, 0, &frequency))
boot_values->ulDCEFClk = frequency;
if (!pp_atomfwctrl_get_clk_information_by_clkid(hwmgr, SMU9_SYSPLL0_ECLK_ID, 0, &frequency))
boot_values->ulEClk = frequency;
if (!pp_atomfwctrl_get_clk_information_by_clkid(hwmgr, SMU9_SYSPLL0_VCLK_ID, 0, &frequency))
boot_values->ulVClk = frequency;
if (!pp_atomfwctrl_get_clk_information_by_clkid(hwmgr, SMU9_SYSPLL0_DCLK_ID, 0, &frequency))
boot_values->ulDClk = frequency;
}
int pp_atomfwctrl_get_vbios_bootup_values(struct pp_hwmgr *hwmgr,
struct pp_atomfwctrl_bios_boot_up_values *boot_values)
{
struct atom_firmware_info_v3_2 *fwinfo_3_2;
struct atom_firmware_info_v3_1 *fwinfo_3_1;
struct atom_common_table_header *info = NULL;
uint16_t ix;
ix = GetIndexIntoMasterDataTable(firmwareinfo);
info = (struct atom_common_table_header *)
smu_atom_get_data_table(hwmgr->adev,
ix, NULL, NULL, NULL);
if (!info) {
pr_info("Error retrieving BIOS firmwareinfo!");
return -EINVAL;
}
if ((info->format_revision == 3) && (info->content_revision == 2)) {
fwinfo_3_2 = (struct atom_firmware_info_v3_2 *)info;
pp_atomfwctrl_copy_vbios_bootup_values_3_2(hwmgr,
boot_values, fwinfo_3_2);
} else if ((info->format_revision == 3) && (info->content_revision == 1)) {
fwinfo_3_1 = (struct atom_firmware_info_v3_1 *)info;
pp_atomfwctrl_copy_vbios_bootup_values_3_1(hwmgr,
boot_values, fwinfo_3_1);
} else {
pr_info("Fw info table revision does not match!");
return -EINVAL;
}
return 0;
}
int pp_atomfwctrl_get_smc_dpm_information(struct pp_hwmgr *hwmgr,
struct pp_atomfwctrl_smc_dpm_parameters *param)
{
struct atom_smc_dpm_info_v4_1 *info;
uint16_t ix;
ix = GetIndexIntoMasterDataTable(smc_dpm_info);
info = (struct atom_smc_dpm_info_v4_1 *)
smu_atom_get_data_table(hwmgr->adev,
ix, NULL, NULL, NULL);
if (!info) {
pr_info("Error retrieving BIOS Table Address!");
return -EINVAL;
}
param->liquid1_i2c_address = info->liquid1_i2c_address;
param->liquid2_i2c_address = info->liquid2_i2c_address;
param->vr_i2c_address = info->vr_i2c_address;
param->plx_i2c_address = info->plx_i2c_address;
param->liquid_i2c_linescl = info->liquid_i2c_linescl;
param->liquid_i2c_linesda = info->liquid_i2c_linesda;
param->vr_i2c_linescl = info->vr_i2c_linescl;
param->vr_i2c_linesda = info->vr_i2c_linesda;
param->plx_i2c_linescl = info->plx_i2c_linescl;
param->plx_i2c_linesda = info->plx_i2c_linesda;
param->vrsensorpresent = info->vrsensorpresent;
param->liquidsensorpresent = info->liquidsensorpresent;
param->maxvoltagestepgfx = info->maxvoltagestepgfx;
param->maxvoltagestepsoc = info->maxvoltagestepsoc;
param->vddgfxvrmapping = info->vddgfxvrmapping;
param->vddsocvrmapping = info->vddsocvrmapping;
param->vddmem0vrmapping = info->vddmem0vrmapping;
param->vddmem1vrmapping = info->vddmem1vrmapping;
param->gfxulvphasesheddingmask = info->gfxulvphasesheddingmask;
param->soculvphasesheddingmask = info->soculvphasesheddingmask;
param->gfxmaxcurrent = info->gfxmaxcurrent;
param->gfxoffset = info->gfxoffset;
param->padding_telemetrygfx = info->padding_telemetrygfx;
param->socmaxcurrent = info->socmaxcurrent;
param->socoffset = info->socoffset;
param->padding_telemetrysoc = info->padding_telemetrysoc;
param->mem0maxcurrent = info->mem0maxcurrent;
param->mem0offset = info->mem0offset;
param->padding_telemetrymem0 = info->padding_telemetrymem0;
param->mem1maxcurrent = info->mem1maxcurrent;
param->mem1offset = info->mem1offset;
param->padding_telemetrymem1 = info->padding_telemetrymem1;
param->acdcgpio = info->acdcgpio;
param->acdcpolarity = info->acdcpolarity;
param->vr0hotgpio = info->vr0hotgpio;
param->vr0hotpolarity = info->vr0hotpolarity;
param->vr1hotgpio = info->vr1hotgpio;
param->vr1hotpolarity = info->vr1hotpolarity;
param->padding1 = info->padding1;
param->padding2 = info->padding2;
param->ledpin0 = info->ledpin0;
param->ledpin1 = info->ledpin1;
param->ledpin2 = info->ledpin2;
param->pllgfxclkspreadenabled = info->pllgfxclkspreadenabled;
param->pllgfxclkspreadpercent = info->pllgfxclkspreadpercent;
param->pllgfxclkspreadfreq = info->pllgfxclkspreadfreq;
param->uclkspreadenabled = info->uclkspreadenabled;
param->uclkspreadpercent = info->uclkspreadpercent;
param->uclkspreadfreq = info->uclkspreadfreq;
param->socclkspreadenabled = info->socclkspreadenabled;
param->socclkspreadpercent = info->socclkspreadpercent;
param->socclkspreadfreq = info->socclkspreadfreq;
param->acggfxclkspreadenabled = info->acggfxclkspreadenabled;
param->acggfxclkspreadpercent = info->acggfxclkspreadpercent;
param->acggfxclkspreadfreq = info->acggfxclkspreadfreq;
param->Vr2_I2C_address = info->Vr2_I2C_address;
return 0;
}

View File

@@ -0,0 +1,244 @@
/*
* 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.
*
*/
#ifndef PP_ATOMFWCTRL_H
#define PP_ATOMFWCTRL_H
#include "hwmgr.h"
typedef enum atom_smu9_syspll0_clock_id BIOS_CLKID;
#define GetIndexIntoMasterCmdTable(FieldName) \
(((char*)(&((struct atom_master_list_of_command_functions_v2_1*)0)->FieldName)-(char*)0)/sizeof(uint16_t))
#define GetIndexIntoMasterDataTable(FieldName) \
(((char*)(&((struct atom_master_list_of_data_tables_v2_1*)0)->FieldName)-(char*)0)/sizeof(uint16_t))
#define PP_ATOMFWCTRL_MAX_VOLTAGE_ENTRIES 32
struct pp_atomfwctrl_voltage_table_entry {
uint16_t value;
uint32_t smio_low;
};
struct pp_atomfwctrl_voltage_table {
uint32_t count;
uint32_t mask_low;
uint32_t phase_delay;
uint8_t psi0_enable;
uint8_t psi1_enable;
uint8_t max_vid_step;
uint8_t telemetry_offset;
uint8_t telemetry_slope;
struct pp_atomfwctrl_voltage_table_entry entries[PP_ATOMFWCTRL_MAX_VOLTAGE_ENTRIES];
};
struct pp_atomfwctrl_gpio_pin_assignment {
uint16_t us_gpio_pin_aindex;
uint8_t uc_gpio_pin_bit_shift;
};
struct pp_atomfwctrl_clock_dividers_soc15 {
uint32_t ulClock; /* the actual clock */
uint32_t ulDid; /* DFS divider */
uint32_t ulPll_fb_mult; /* Feedback Multiplier: bit 8:0 int, bit 15:12 post_div, bit 31:16 frac */
uint32_t ulPll_ss_fbsmult; /* Spread FB Multiplier: bit 8:0 int, bit 31:16 frac */
uint16_t usPll_ss_slew_frac;
uint8_t ucPll_ss_enable;
uint8_t ucReserve;
uint32_t ulReserve[2];
};
struct pp_atomfwctrl_avfs_parameters {
uint32_t ulMaxVddc;
uint32_t ulMinVddc;
uint32_t ulMeanNsigmaAcontant0;
uint32_t ulMeanNsigmaAcontant1;
uint32_t ulMeanNsigmaAcontant2;
uint16_t usMeanNsigmaDcTolSigma;
uint16_t usMeanNsigmaPlatformMean;
uint16_t usMeanNsigmaPlatformSigma;
uint32_t ulGbVdroopTableCksoffA0;
uint32_t ulGbVdroopTableCksoffA1;
uint32_t ulGbVdroopTableCksoffA2;
uint32_t ulGbVdroopTableCksonA0;
uint32_t ulGbVdroopTableCksonA1;
uint32_t ulGbVdroopTableCksonA2;
uint32_t ulGbFuseTableCksoffM1;
uint32_t ulGbFuseTableCksoffM2;
uint32_t ulGbFuseTableCksoffB;
uint32_t ulGbFuseTableCksonM1;
uint32_t ulGbFuseTableCksonM2;
uint32_t ulGbFuseTableCksonB;
uint8_t ucEnableGbVdroopTableCkson;
uint8_t ucEnableGbFuseTableCkson;
uint16_t usPsmAgeComfactor;
uint32_t ulDispclk2GfxclkM1;
uint32_t ulDispclk2GfxclkM2;
uint32_t ulDispclk2GfxclkB;
uint32_t ulDcefclk2GfxclkM1;
uint32_t ulDcefclk2GfxclkM2;
uint32_t ulDcefclk2GfxclkB;
uint32_t ulPixelclk2GfxclkM1;
uint32_t ulPixelclk2GfxclkM2;
uint32_t ulPixelclk2GfxclkB;
uint32_t ulPhyclk2GfxclkM1;
uint32_t ulPhyclk2GfxclkM2;
uint32_t ulPhyclk2GfxclkB;
uint32_t ulAcgGbVdroopTableA0;
uint32_t ulAcgGbVdroopTableA1;
uint32_t ulAcgGbVdroopTableA2;
uint32_t ulAcgGbFuseTableM1;
uint32_t ulAcgGbFuseTableM2;
uint32_t ulAcgGbFuseTableB;
uint32_t ucAcgEnableGbVdroopTable;
uint32_t ucAcgEnableGbFuseTable;
};
struct pp_atomfwctrl_gpio_parameters {
uint8_t ucAcDcGpio;
uint8_t ucAcDcPolarity;
uint8_t ucVR0HotGpio;
uint8_t ucVR0HotPolarity;
uint8_t ucVR1HotGpio;
uint8_t ucVR1HotPolarity;
uint8_t ucFwCtfGpio;
uint8_t ucFwCtfPolarity;
};
struct pp_atomfwctrl_bios_boot_up_values {
uint32_t ulRevision;
uint32_t ulGfxClk;
uint32_t ulUClk;
uint32_t ulSocClk;
uint32_t ulDCEFClk;
uint32_t ulEClk;
uint32_t ulVClk;
uint32_t ulDClk;
uint32_t ulFClk;
uint16_t usVddc;
uint16_t usVddci;
uint16_t usMvddc;
uint16_t usVddGfx;
uint8_t ucCoolingID;
};
struct pp_atomfwctrl_smc_dpm_parameters
{
uint8_t liquid1_i2c_address;
uint8_t liquid2_i2c_address;
uint8_t vr_i2c_address;
uint8_t plx_i2c_address;
uint8_t liquid_i2c_linescl;
uint8_t liquid_i2c_linesda;
uint8_t vr_i2c_linescl;
uint8_t vr_i2c_linesda;
uint8_t plx_i2c_linescl;
uint8_t plx_i2c_linesda;
uint8_t vrsensorpresent;
uint8_t liquidsensorpresent;
uint16_t maxvoltagestepgfx;
uint16_t maxvoltagestepsoc;
uint8_t vddgfxvrmapping;
uint8_t vddsocvrmapping;
uint8_t vddmem0vrmapping;
uint8_t vddmem1vrmapping;
uint8_t gfxulvphasesheddingmask;
uint8_t soculvphasesheddingmask;
uint16_t gfxmaxcurrent;
uint8_t gfxoffset;
uint8_t padding_telemetrygfx;
uint16_t socmaxcurrent;
uint8_t socoffset;
uint8_t padding_telemetrysoc;
uint16_t mem0maxcurrent;
uint8_t mem0offset;
uint8_t padding_telemetrymem0;
uint16_t mem1maxcurrent;
uint8_t mem1offset;
uint8_t padding_telemetrymem1;
uint8_t acdcgpio;
uint8_t acdcpolarity;
uint8_t vr0hotgpio;
uint8_t vr0hotpolarity;
uint8_t vr1hotgpio;
uint8_t vr1hotpolarity;
uint8_t padding1;
uint8_t padding2;
uint8_t ledpin0;
uint8_t ledpin1;
uint8_t ledpin2;
uint8_t pllgfxclkspreadenabled;
uint8_t pllgfxclkspreadpercent;
uint16_t pllgfxclkspreadfreq;
uint8_t uclkspreadenabled;
uint8_t uclkspreadpercent;
uint16_t uclkspreadfreq;
uint8_t socclkspreadenabled;
uint8_t socclkspreadpercent;
uint16_t socclkspreadfreq;
uint8_t acggfxclkspreadenabled;
uint8_t acggfxclkspreadpercent;
uint16_t acggfxclkspreadfreq;
uint8_t Vr2_I2C_address;
};
int pp_atomfwctrl_get_gpu_pll_dividers_vega10(struct pp_hwmgr *hwmgr,
uint32_t clock_type, uint32_t clock_value,
struct pp_atomfwctrl_clock_dividers_soc15 *dividers);
int pp_atomfwctrl_enter_self_refresh(struct pp_hwmgr *hwmgr);
bool pp_atomfwctrl_get_pp_assign_pin(struct pp_hwmgr *hwmgr, const uint32_t pin_id,
struct pp_atomfwctrl_gpio_pin_assignment *gpio_pin_assignment);
int pp_atomfwctrl_get_voltage_table_v4(struct pp_hwmgr *hwmgr, uint8_t voltage_type,
uint8_t voltage_mode, struct pp_atomfwctrl_voltage_table *voltage_table);
bool pp_atomfwctrl_is_voltage_controlled_by_gpio_v4(struct pp_hwmgr *hwmgr,
uint8_t voltage_type, uint8_t voltage_mode);
int pp_atomfwctrl_get_avfs_information(struct pp_hwmgr *hwmgr,
struct pp_atomfwctrl_avfs_parameters *param);
int pp_atomfwctrl_get_gpio_information(struct pp_hwmgr *hwmgr,
struct pp_atomfwctrl_gpio_parameters *param);
int pp_atomfwctrl_get_vbios_bootup_values(struct pp_hwmgr *hwmgr,
struct pp_atomfwctrl_bios_boot_up_values *boot_values);
int pp_atomfwctrl_get_smc_dpm_information(struct pp_hwmgr *hwmgr,
struct pp_atomfwctrl_smc_dpm_parameters *param);
int pp_atomfwctrl_get_clk_information_by_clkid(struct pp_hwmgr *hwmgr,
uint8_t clk_id, uint8_t syspll_id,
uint32_t *frequency);
#endif

View File

@@ -0,0 +1,555 @@
/*
* Copyright 2015 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 <asm/div64.h>
#define SHIFT_AMOUNT 16 /* We multiply all original integers with 2^SHIFT_AMOUNT to get the fInt representation */
#define PRECISION 5 /* Change this value to change the number of decimal places in the final output - 5 is a good default */
#define SHIFTED_2 (2 << SHIFT_AMOUNT)
#define MAX (1 << (SHIFT_AMOUNT - 1)) - 1 /* 32767 - Might change in the future */
/* -------------------------------------------------------------------------------
* NEW TYPE - fINT
* -------------------------------------------------------------------------------
* A variable of type fInt can be accessed in 3 ways using the dot (.) operator
* fInt A;
* A.full => The full number as it is. Generally not easy to read
* A.partial.real => Only the integer portion
* A.partial.decimal => Only the fractional portion
*/
typedef union _fInt {
int full;
struct _partial {
unsigned int decimal: SHIFT_AMOUNT; /*Needs to always be unsigned*/
int real: 32 - SHIFT_AMOUNT;
} partial;
} fInt;
/* -------------------------------------------------------------------------------
* Function Declarations
* -------------------------------------------------------------------------------
*/
static fInt ConvertToFraction(int); /* Use this to convert an INT to a FINT */
static fInt Convert_ULONG_ToFraction(uint32_t); /* Use this to convert an uint32_t to a FINT */
static fInt GetScaledFraction(int, int); /* Use this to convert an INT to a FINT after scaling it by a factor */
static int ConvertBackToInteger(fInt); /* Convert a FINT back to an INT that is scaled by 1000 (i.e. last 3 digits are the decimal digits) */
static fInt fNegate(fInt); /* Returns -1 * input fInt value */
static fInt fAdd (fInt, fInt); /* Returns the sum of two fInt numbers */
static fInt fSubtract (fInt A, fInt B); /* Returns A-B - Sometimes easier than Adding negative numbers */
static fInt fMultiply (fInt, fInt); /* Returns the product of two fInt numbers */
static fInt fDivide (fInt A, fInt B); /* Returns A/B */
static fInt fGetSquare(fInt); /* Returns the square of a fInt number */
static fInt fSqrt(fInt); /* Returns the Square Root of a fInt number */
static int uAbs(int); /* Returns the Absolute value of the Int */
static int uPow(int base, int exponent); /* Returns base^exponent an INT */
static void SolveQuadracticEqn(fInt, fInt, fInt, fInt[]); /* Returns the 2 roots via the array */
static bool Equal(fInt, fInt); /* Returns true if two fInts are equal to each other */
static bool GreaterThan(fInt A, fInt B); /* Returns true if A > B */
static fInt fExponential(fInt exponent); /* Can be used to calculate e^exponent */
static fInt fNaturalLog(fInt value); /* Can be used to calculate ln(value) */
/* Fuse decoding functions
* -------------------------------------------------------------------------------------
*/
static fInt fDecodeLinearFuse(uint32_t fuse_value, fInt f_min, fInt f_range, uint32_t bitlength);
static fInt fDecodeLogisticFuse(uint32_t fuse_value, fInt f_average, fInt f_range, uint32_t bitlength);
static fInt fDecodeLeakageID (uint32_t leakageID_fuse, fInt ln_max_div_min, fInt f_min, uint32_t bitlength);
/* Internal Support Functions - Use these ONLY for testing or adding to internal functions
* -------------------------------------------------------------------------------------
* Some of the following functions take two INTs as their input - This is unsafe for a variety of reasons.
*/
static fInt Divide (int, int); /* Divide two INTs and return result as FINT */
static fInt fNegate(fInt);
static int uGetScaledDecimal (fInt); /* Internal function */
static int GetReal (fInt A); /* Internal function */
/* -------------------------------------------------------------------------------------
* TROUBLESHOOTING INFORMATION
* -------------------------------------------------------------------------------------
* 1) ConvertToFraction - InputOutOfRangeException: Only accepts numbers smaller than MAX (default: 32767)
* 2) fAdd - OutputOutOfRangeException: Output bigger than MAX (default: 32767)
* 3) fMultiply - OutputOutOfRangeException:
* 4) fGetSquare - OutputOutOfRangeException:
* 5) fDivide - DivideByZeroException
* 6) fSqrt - NegativeSquareRootException: Input cannot be a negative number
*/
/* -------------------------------------------------------------------------------------
* START OF CODE
* -------------------------------------------------------------------------------------
*/
static fInt fExponential(fInt exponent) /*Can be used to calculate e^exponent*/
{
uint32_t i;
bool bNegated = false;
fInt fPositiveOne = ConvertToFraction(1);
fInt fZERO = ConvertToFraction(0);
fInt lower_bound = Divide(78, 10000);
fInt solution = fPositiveOne; /*Starting off with baseline of 1 */
fInt error_term;
static const uint32_t k_array[11] = {55452, 27726, 13863, 6931, 4055, 2231, 1178, 606, 308, 155, 78};
static const uint32_t expk_array[11] = {2560000, 160000, 40000, 20000, 15000, 12500, 11250, 10625, 10313, 10156, 10078};
if (GreaterThan(fZERO, exponent)) {
exponent = fNegate(exponent);
bNegated = true;
}
while (GreaterThan(exponent, lower_bound)) {
for (i = 0; i < 11; i++) {
if (GreaterThan(exponent, GetScaledFraction(k_array[i], 10000))) {
exponent = fSubtract(exponent, GetScaledFraction(k_array[i], 10000));
solution = fMultiply(solution, GetScaledFraction(expk_array[i], 10000));
}
}
}
error_term = fAdd(fPositiveOne, exponent);
solution = fMultiply(solution, error_term);
if (bNegated)
solution = fDivide(fPositiveOne, solution);
return solution;
}
static fInt fNaturalLog(fInt value)
{
uint32_t i;
fInt upper_bound = Divide(8, 1000);
fInt fNegativeOne = ConvertToFraction(-1);
fInt solution = ConvertToFraction(0); /*Starting off with baseline of 0 */
fInt error_term;
static const uint32_t k_array[10] = {160000, 40000, 20000, 15000, 12500, 11250, 10625, 10313, 10156, 10078};
static const uint32_t logk_array[10] = {27726, 13863, 6931, 4055, 2231, 1178, 606, 308, 155, 78};
while (GreaterThan(fAdd(value, fNegativeOne), upper_bound)) {
for (i = 0; i < 10; i++) {
if (GreaterThan(value, GetScaledFraction(k_array[i], 10000))) {
value = fDivide(value, GetScaledFraction(k_array[i], 10000));
solution = fAdd(solution, GetScaledFraction(logk_array[i], 10000));
}
}
}
error_term = fAdd(fNegativeOne, value);
return (fAdd(solution, error_term));
}
static fInt fDecodeLinearFuse(uint32_t fuse_value, fInt f_min, fInt f_range, uint32_t bitlength)
{
fInt f_fuse_value = Convert_ULONG_ToFraction(fuse_value);
fInt f_bit_max_value = Convert_ULONG_ToFraction((uPow(2, bitlength)) - 1);
fInt f_decoded_value;
f_decoded_value = fDivide(f_fuse_value, f_bit_max_value);
f_decoded_value = fMultiply(f_decoded_value, f_range);
f_decoded_value = fAdd(f_decoded_value, f_min);
return f_decoded_value;
}
static fInt fDecodeLogisticFuse(uint32_t fuse_value, fInt f_average, fInt f_range, uint32_t bitlength)
{
fInt f_fuse_value = Convert_ULONG_ToFraction(fuse_value);
fInt f_bit_max_value = Convert_ULONG_ToFraction((uPow(2, bitlength)) - 1);
fInt f_CONSTANT_NEG13 = ConvertToFraction(-13);
fInt f_CONSTANT1 = ConvertToFraction(1);
fInt f_decoded_value;
f_decoded_value = fSubtract(fDivide(f_bit_max_value, f_fuse_value), f_CONSTANT1);
f_decoded_value = fNaturalLog(f_decoded_value);
f_decoded_value = fMultiply(f_decoded_value, fDivide(f_range, f_CONSTANT_NEG13));
f_decoded_value = fAdd(f_decoded_value, f_average);
return f_decoded_value;
}
static fInt fDecodeLeakageID (uint32_t leakageID_fuse, fInt ln_max_div_min, fInt f_min, uint32_t bitlength)
{
fInt fLeakage;
fInt f_bit_max_value = Convert_ULONG_ToFraction((uPow(2, bitlength)) - 1);
fLeakage = fMultiply(ln_max_div_min, Convert_ULONG_ToFraction(leakageID_fuse));
fLeakage = fDivide(fLeakage, f_bit_max_value);
fLeakage = fExponential(fLeakage);
fLeakage = fMultiply(fLeakage, f_min);
return fLeakage;
}
static fInt ConvertToFraction(int X) /*Add all range checking here. Is it possible to make fInt a private declaration? */
{
fInt temp;
if (X <= MAX)
temp.full = (X << SHIFT_AMOUNT);
else
temp.full = 0;
return temp;
}
static fInt fNegate(fInt X)
{
fInt CONSTANT_NEGONE = ConvertToFraction(-1);
return (fMultiply(X, CONSTANT_NEGONE));
}
static fInt Convert_ULONG_ToFraction(uint32_t X)
{
fInt temp;
if (X <= MAX)
temp.full = (X << SHIFT_AMOUNT);
else
temp.full = 0;
return temp;
}
static fInt GetScaledFraction(int X, int factor)
{
int times_shifted, factor_shifted;
bool bNEGATED;
fInt fValue;
times_shifted = 0;
factor_shifted = 0;
bNEGATED = false;
if (X < 0) {
X = -1*X;
bNEGATED = true;
}
if (factor < 0) {
factor = -1*factor;
bNEGATED = !bNEGATED; /*If bNEGATED = true due to X < 0, this will cover the case of negative cancelling negative */
}
if ((X > MAX) || factor > MAX) {
if ((X/factor) <= MAX) {
while (X > MAX) {
X = X >> 1;
times_shifted++;
}
while (factor > MAX) {
factor = factor >> 1;
factor_shifted++;
}
} else {
fValue.full = 0;
return fValue;
}
}
if (factor == 1)
return ConvertToFraction(X);
fValue = fDivide(ConvertToFraction(X * uPow(-1, bNEGATED)), ConvertToFraction(factor));
fValue.full = fValue.full << times_shifted;
fValue.full = fValue.full >> factor_shifted;
return fValue;
}
/* Addition using two fInts */
static fInt fAdd (fInt X, fInt Y)
{
fInt Sum;
Sum.full = X.full + Y.full;
return Sum;
}
/* Addition using two fInts */
static fInt fSubtract (fInt X, fInt Y)
{
fInt Difference;
Difference.full = X.full - Y.full;
return Difference;
}
static bool Equal(fInt A, fInt B)
{
if (A.full == B.full)
return true;
else
return false;
}
static bool GreaterThan(fInt A, fInt B)
{
if (A.full > B.full)
return true;
else
return false;
}
static fInt fMultiply (fInt X, fInt Y) /* Uses 64-bit integers (int64_t) */
{
fInt Product;
int64_t tempProduct;
bool X_LessThanOne, Y_LessThanOne;
X_LessThanOne = (X.partial.real == 0 && X.partial.decimal != 0 && X.full >= 0);
Y_LessThanOne = (Y.partial.real == 0 && Y.partial.decimal != 0 && Y.full >= 0);
/*The following is for a very specific common case: Non-zero number with ONLY fractional portion*/
/* TEMPORARILY DISABLED - CAN BE USED TO IMPROVE PRECISION
if (X_LessThanOne && Y_LessThanOne) {
Product.full = X.full * Y.full;
return Product
}*/
tempProduct = ((int64_t)X.full) * ((int64_t)Y.full); /*Q(16,16)*Q(16,16) = Q(32, 32) - Might become a negative number! */
tempProduct = tempProduct >> 16; /*Remove lagging 16 bits - Will lose some precision from decimal; */
Product.full = (int)tempProduct; /*The int64_t will lose the leading 16 bits that were part of the integer portion */
return Product;
}
static fInt fDivide (fInt X, fInt Y)
{
fInt fZERO, fQuotient;
int64_t longlongX, longlongY;
fZERO = ConvertToFraction(0);
if (Equal(Y, fZERO))
return fZERO;
longlongX = (int64_t)X.full;
longlongY = (int64_t)Y.full;
longlongX = longlongX << 16; /*Q(16,16) -> Q(32,32) */
div64_s64(longlongX, longlongY); /*Q(32,32) divided by Q(16,16) = Q(16,16) Back to original format */
fQuotient.full = (int)longlongX;
return fQuotient;
}
static int ConvertBackToInteger (fInt A) /*THIS is the function that will be used to check with the Golden settings table*/
{
fInt fullNumber, scaledDecimal, scaledReal;
scaledReal.full = GetReal(A) * uPow(10, PRECISION-1); /* DOUBLE CHECK THISSSS!!! */
scaledDecimal.full = uGetScaledDecimal(A);
fullNumber = fAdd(scaledDecimal,scaledReal);
return fullNumber.full;
}
static fInt fGetSquare(fInt A)
{
return fMultiply(A,A);
}
/* x_new = x_old - (x_old^2 - C) / (2 * x_old) */
static fInt fSqrt(fInt num)
{
fInt F_divide_Fprime, Fprime;
fInt test;
fInt twoShifted;
int seed, counter, error;
fInt x_new, x_old, C, y;
fInt fZERO = ConvertToFraction(0);
/* (0 > num) is the same as (num < 0), i.e., num is negative */
if (GreaterThan(fZERO, num) || Equal(fZERO, num))
return fZERO;
C = num;
if (num.partial.real > 3000)
seed = 60;
else if (num.partial.real > 1000)
seed = 30;
else if (num.partial.real > 100)
seed = 10;
else
seed = 2;
counter = 0;
if (Equal(num, fZERO)) /*Square Root of Zero is zero */
return fZERO;
twoShifted = ConvertToFraction(2);
x_new = ConvertToFraction(seed);
do {
counter++;
x_old.full = x_new.full;
test = fGetSquare(x_old); /*1.75*1.75 is reverting back to 1 when shifted down */
y = fSubtract(test, C); /*y = f(x) = x^2 - C; */
Fprime = fMultiply(twoShifted, x_old);
F_divide_Fprime = fDivide(y, Fprime);
x_new = fSubtract(x_old, F_divide_Fprime);
error = ConvertBackToInteger(x_new) - ConvertBackToInteger(x_old);
if (counter > 20) /*20 is already way too many iterations. If we dont have an answer by then, we never will*/
return x_new;
} while (uAbs(error) > 0);
return (x_new);
}
static void SolveQuadracticEqn(fInt A, fInt B, fInt C, fInt Roots[])
{
fInt *pRoots = &Roots[0];
fInt temp, root_first, root_second;
fInt f_CONSTANT10, f_CONSTANT100;
f_CONSTANT100 = ConvertToFraction(100);
f_CONSTANT10 = ConvertToFraction(10);
while(GreaterThan(A, f_CONSTANT100) || GreaterThan(B, f_CONSTANT100) || GreaterThan(C, f_CONSTANT100)) {
A = fDivide(A, f_CONSTANT10);
B = fDivide(B, f_CONSTANT10);
C = fDivide(C, f_CONSTANT10);
}
temp = fMultiply(ConvertToFraction(4), A); /* root = 4*A */
temp = fMultiply(temp, C); /* root = 4*A*C */
temp = fSubtract(fGetSquare(B), temp); /* root = b^2 - 4AC */
temp = fSqrt(temp); /*root = Sqrt (b^2 - 4AC); */
root_first = fSubtract(fNegate(B), temp); /* b - Sqrt(b^2 - 4AC) */
root_second = fAdd(fNegate(B), temp); /* b + Sqrt(b^2 - 4AC) */
root_first = fDivide(root_first, ConvertToFraction(2)); /* [b +- Sqrt(b^2 - 4AC)]/[2] */
root_first = fDivide(root_first, A); /*[b +- Sqrt(b^2 - 4AC)]/[2*A] */
root_second = fDivide(root_second, ConvertToFraction(2)); /* [b +- Sqrt(b^2 - 4AC)]/[2] */
root_second = fDivide(root_second, A); /*[b +- Sqrt(b^2 - 4AC)]/[2*A] */
*(pRoots + 0) = root_first;
*(pRoots + 1) = root_second;
}
/* -----------------------------------------------------------------------------
* SUPPORT FUNCTIONS
* -----------------------------------------------------------------------------
*/
/* Conversion Functions */
static int GetReal (fInt A)
{
return (A.full >> SHIFT_AMOUNT);
}
static fInt Divide (int X, int Y)
{
fInt A, B, Quotient;
A.full = X << SHIFT_AMOUNT;
B.full = Y << SHIFT_AMOUNT;
Quotient = fDivide(A, B);
return Quotient;
}
static int uGetScaledDecimal (fInt A) /*Converts the fractional portion to whole integers - Costly function */
{
int dec[PRECISION];
int i, scaledDecimal = 0, tmp = A.partial.decimal;
for (i = 0; i < PRECISION; i++) {
dec[i] = tmp / (1 << SHIFT_AMOUNT);
tmp = tmp - ((1 << SHIFT_AMOUNT)*dec[i]);
tmp *= 10;
scaledDecimal = scaledDecimal + dec[i]*uPow(10, PRECISION - 1 -i);
}
return scaledDecimal;
}
static int uPow(int base, int power)
{
if (power == 0)
return 1;
else
return (base)*uPow(base, power - 1);
}
static int uAbs(int X)
{
if (X < 0)
return (X * -1);
else
return X;
}
static fInt fRoundUpByStepSize(fInt A, fInt fStepSize, bool error_term)
{
fInt solution;
solution = fDivide(A, fStepSize);
solution.partial.decimal = 0; /*All fractional digits changes to 0 */
if (error_term)
solution.partial.real += 1; /*Error term of 1 added */
solution = fMultiply(solution, fStepSize);
solution = fAdd(solution, fStepSize);
return solution;
}

View File

@@ -0,0 +1,64 @@
/*
* Copyright 2015 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/types.h>
#include "atom-types.h"
#include "atombios.h"
#include "pppcielanes.h"
/** \file
* Functions related to PCIe lane changes.
*/
/* For converting from number of lanes to lane bits. */
static const unsigned char pp_r600_encode_lanes[] = {
0, /* 0 Not Supported */
1, /* 1 Lane */
2, /* 2 Lanes */
0, /* 3 Not Supported */
3, /* 4 Lanes */
0, /* 5 Not Supported */
0, /* 6 Not Supported */
0, /* 7 Not Supported */
4, /* 8 Lanes */
0, /* 9 Not Supported */
0, /* 10 Not Supported */
0, /* 11 Not Supported */
5, /* 12 Lanes (Not actually supported) */
0, /* 13 Not Supported */
0, /* 14 Not Supported */
0, /* 15 Not Supported */
6 /* 16 Lanes */
};
static const unsigned char pp_r600_decoded_lanes[8] = { 16, 1, 2, 4, 8, 12, 16, };
uint8_t encode_pcie_lane_width(uint32_t num_lanes)
{
return pp_r600_encode_lanes[num_lanes];
}
uint8_t decode_pcie_lane_width(uint32_t num_lanes)
{
return pp_r600_decoded_lanes[num_lanes];
}

View File

@@ -0,0 +1,31 @@
/*
* Copyright 2015 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.
*
*/
#ifndef PP_PCIELANES_H
#define PP_PCIELANES_H
extern uint8_t encode_pcie_lane_width(uint32_t num_lanes);
extern uint8_t decode_pcie_lane_width(uint32_t num_lanes);
#endif

View File

@@ -0,0 +1,436 @@
/*
* Copyright 2015 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.
*
*/
#ifndef TONGA_PPTABLE_H
#define TONGA_PPTABLE_H
/** \file
* This is a PowerPlay table header file
*/
#pragma pack(push, 1)
#include "hwmgr.h"
#define ATOM_TONGA_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK 0x0f
#define ATOM_TONGA_PP_FANPARAMETERS_NOFAN 0x80 /* No fan is connected to this controller. */
#define ATOM_TONGA_PP_THERMALCONTROLLER_NONE 0
#define ATOM_TONGA_PP_THERMALCONTROLLER_LM96163 17
#define ATOM_TONGA_PP_THERMALCONTROLLER_TONGA 21
#define ATOM_TONGA_PP_THERMALCONTROLLER_FIJI 22
/*
* Thermal controller 'combo type' to use an external controller for Fan control and an internal controller for thermal.
* We probably should reserve the bit 0x80 for this use.
* To keep the number of these types low we should also use the same code for all ASICs (i.e. do not distinguish RV6xx and RV7xx Internal here).
* The driver can pick the correct internal controller based on the ASIC.
*/
#define ATOM_TONGA_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL 0x89 /* ADT7473 Fan Control + Internal Thermal Controller */
#define ATOM_TONGA_PP_THERMALCONTROLLER_EMC2103_WITH_INTERNAL 0x8D /* EMC2103 Fan Control + Internal Thermal Controller */
/*/* ATOM_TONGA_POWERPLAYTABLE::ulPlatformCaps */
#define ATOM_TONGA_PP_PLATFORM_CAP_VDDGFX_CONTROL 0x1 /* This cap indicates whether vddgfx will be a separated power rail. */
#define ATOM_TONGA_PP_PLATFORM_CAP_POWERPLAY 0x2 /* This cap indicates whether this is a mobile part and CCC need to show Powerplay page. */
#define ATOM_TONGA_PP_PLATFORM_CAP_SBIOSPOWERSOURCE 0x4 /* This cap indicates whether power source notificaiton is done by SBIOS directly. */
#define ATOM_TONGA_PP_PLATFORM_CAP_DISABLE_VOLTAGE_ISLAND 0x8 /* Enable the option to overwrite voltage island feature to be disabled, regardless of VddGfx power rail support. */
#define ____RETIRE16____ 0x10
#define ATOM_TONGA_PP_PLATFORM_CAP_HARDWAREDC 0x20 /* This cap indicates whether power source notificaiton is done by GPIO directly. */
#define ____RETIRE64____ 0x40
#define ____RETIRE128____ 0x80
#define ____RETIRE256____ 0x100
#define ____RETIRE512____ 0x200
#define ____RETIRE1024____ 0x400
#define ____RETIRE2048____ 0x800
#define ATOM_TONGA_PP_PLATFORM_CAP_MVDD_CONTROL 0x1000 /* This cap indicates dynamic MVDD is required. Uncheck to disable it. */
#define ____RETIRE2000____ 0x2000
#define ____RETIRE4000____ 0x4000
#define ATOM_TONGA_PP_PLATFORM_CAP_VDDCI_CONTROL 0x8000 /* This cap indicates dynamic VDDCI is required. Uncheck to disable it. */
#define ____RETIRE10000____ 0x10000
#define ATOM_TONGA_PP_PLATFORM_CAP_BACO 0x20000 /* Enable to indicate the driver supports BACO state. */
#define ATOM_TONGA_PP_PLATFORM_CAP_OUTPUT_THERMAL2GPIO17 0x100000 /* Enable to indicate the driver supports thermal2GPIO17. */
#define ATOM_TONGA_PP_PLATFORM_COMBINE_PCC_WITH_THERMAL_SIGNAL 0x1000000 /* Enable to indicate if thermal and PCC are sharing the same GPIO */
#define ATOM_TONGA_PLATFORM_LOAD_POST_PRODUCTION_FIRMWARE 0x2000000
/* ATOM_PPLIB_NONCLOCK_INFO::usClassification */
#define ATOM_PPLIB_CLASSIFICATION_UI_MASK 0x0007
#define ATOM_PPLIB_CLASSIFICATION_UI_SHIFT 0
#define ATOM_PPLIB_CLASSIFICATION_UI_NONE 0
#define ATOM_PPLIB_CLASSIFICATION_UI_BATTERY 1
#define ATOM_PPLIB_CLASSIFICATION_UI_BALANCED 3
#define ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE 5
/* 2, 4, 6, 7 are reserved */
#define ATOM_PPLIB_CLASSIFICATION_BOOT 0x0008
#define ATOM_PPLIB_CLASSIFICATION_THERMAL 0x0010
#define ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE 0x0020
#define ATOM_PPLIB_CLASSIFICATION_REST 0x0040
#define ATOM_PPLIB_CLASSIFICATION_FORCED 0x0080
#define ATOM_PPLIB_CLASSIFICATION_ACPI 0x1000
/* ATOM_PPLIB_NONCLOCK_INFO::usClassification2 */
#define ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2 0x0001
#define ATOM_Tonga_DISALLOW_ON_DC 0x00004000
#define ATOM_Tonga_ENABLE_VARIBRIGHT 0x00008000
#define ATOM_Tonga_TABLE_REVISION_TONGA 7
typedef struct _ATOM_Tonga_POWERPLAYTABLE {
ATOM_COMMON_TABLE_HEADER sHeader;
UCHAR ucTableRevision;
USHORT usTableSize; /*the size of header structure */
ULONG ulGoldenPPID;
ULONG ulGoldenRevision;
USHORT usFormatID;
USHORT usVoltageTime; /*in microseconds */
ULONG ulPlatformCaps; /*See ATOM_Tonga_CAPS_* */
ULONG ulMaxODEngineClock; /*For Overdrive. */
ULONG ulMaxODMemoryClock; /*For Overdrive. */
USHORT usPowerControlLimit;
USHORT usUlvVoltageOffset; /*in mv units */
USHORT usStateArrayOffset; /*points to ATOM_Tonga_State_Array */
USHORT usFanTableOffset; /*points to ATOM_Tonga_Fan_Table */
USHORT usThermalControllerOffset; /*points to ATOM_Tonga_Thermal_Controller */
USHORT usReserv; /*CustomThermalPolicy removed for Tonga. Keep this filed as reserved. */
USHORT usMclkDependencyTableOffset; /*points to ATOM_Tonga_MCLK_Dependency_Table */
USHORT usSclkDependencyTableOffset; /*points to ATOM_Tonga_SCLK_Dependency_Table */
USHORT usVddcLookupTableOffset; /*points to ATOM_Tonga_Voltage_Lookup_Table */
USHORT usVddgfxLookupTableOffset; /*points to ATOM_Tonga_Voltage_Lookup_Table */
USHORT usMMDependencyTableOffset; /*points to ATOM_Tonga_MM_Dependency_Table */
USHORT usVCEStateTableOffset; /*points to ATOM_Tonga_VCE_State_Table; */
USHORT usPPMTableOffset; /*points to ATOM_Tonga_PPM_Table */
USHORT usPowerTuneTableOffset; /*points to ATOM_PowerTune_Table */
USHORT usHardLimitTableOffset; /*points to ATOM_Tonga_Hard_Limit_Table */
USHORT usPCIETableOffset; /*points to ATOM_Tonga_PCIE_Table */
USHORT usGPIOTableOffset; /*points to ATOM_Tonga_GPIO_Table */
USHORT usReserved[6]; /*TODO: modify reserved size to fit structure aligning */
} ATOM_Tonga_POWERPLAYTABLE;
typedef struct _ATOM_Tonga_State {
UCHAR ucEngineClockIndexHigh;
UCHAR ucEngineClockIndexLow;
UCHAR ucMemoryClockIndexHigh;
UCHAR ucMemoryClockIndexLow;
UCHAR ucPCIEGenLow;
UCHAR ucPCIEGenHigh;
UCHAR ucPCIELaneLow;
UCHAR ucPCIELaneHigh;
USHORT usClassification;
ULONG ulCapsAndSettings;
USHORT usClassification2;
UCHAR ucUnused[4];
} ATOM_Tonga_State;
typedef struct _ATOM_Tonga_State_Array {
UCHAR ucRevId;
UCHAR ucNumEntries; /* Number of entries. */
ATOM_Tonga_State entries[1]; /* Dynamically allocate entries. */
} ATOM_Tonga_State_Array;
typedef struct _ATOM_Tonga_MCLK_Dependency_Record {
UCHAR ucVddcInd; /* Vddc voltage */
USHORT usVddci;
USHORT usVddgfxOffset; /* Offset relative to Vddc voltage */
USHORT usMvdd;
ULONG ulMclk;
USHORT usReserved;
} ATOM_Tonga_MCLK_Dependency_Record;
typedef struct _ATOM_Tonga_MCLK_Dependency_Table {
UCHAR ucRevId;
UCHAR ucNumEntries; /* Number of entries. */
ATOM_Tonga_MCLK_Dependency_Record entries[1]; /* Dynamically allocate entries. */
} ATOM_Tonga_MCLK_Dependency_Table;
typedef struct _ATOM_Tonga_SCLK_Dependency_Record {
UCHAR ucVddInd; /* Base voltage */
USHORT usVddcOffset; /* Offset relative to base voltage */
ULONG ulSclk;
USHORT usEdcCurrent;
UCHAR ucReliabilityTemperature;
UCHAR ucCKSVOffsetandDisable; /* Bits 0~6: Voltage offset for CKS, Bit 7: Disable/enable for the SCLK level. */
} ATOM_Tonga_SCLK_Dependency_Record;
typedef struct _ATOM_Tonga_SCLK_Dependency_Table {
UCHAR ucRevId;
UCHAR ucNumEntries; /* Number of entries. */
ATOM_Tonga_SCLK_Dependency_Record entries[1]; /* Dynamically allocate entries. */
} ATOM_Tonga_SCLK_Dependency_Table;
typedef struct _ATOM_Polaris_SCLK_Dependency_Record {
UCHAR ucVddInd; /* Base voltage */
USHORT usVddcOffset; /* Offset relative to base voltage */
ULONG ulSclk;
USHORT usEdcCurrent;
UCHAR ucReliabilityTemperature;
UCHAR ucCKSVOffsetandDisable; /* Bits 0~6: Voltage offset for CKS, Bit 7: Disable/enable for the SCLK level. */
ULONG ulSclkOffset;
} ATOM_Polaris_SCLK_Dependency_Record;
typedef struct _ATOM_Polaris_SCLK_Dependency_Table {
UCHAR ucRevId;
UCHAR ucNumEntries; /* Number of entries. */
ATOM_Polaris_SCLK_Dependency_Record entries[1]; /* Dynamically allocate entries. */
} ATOM_Polaris_SCLK_Dependency_Table;
typedef struct _ATOM_Tonga_PCIE_Record {
UCHAR ucPCIEGenSpeed;
UCHAR usPCIELaneWidth;
UCHAR ucReserved[2];
} ATOM_Tonga_PCIE_Record;
typedef struct _ATOM_Tonga_PCIE_Table {
UCHAR ucRevId;
UCHAR ucNumEntries; /* Number of entries. */
ATOM_Tonga_PCIE_Record entries[1]; /* Dynamically allocate entries. */
} ATOM_Tonga_PCIE_Table;
typedef struct _ATOM_Polaris10_PCIE_Record {
UCHAR ucPCIEGenSpeed;
UCHAR usPCIELaneWidth;
UCHAR ucReserved[2];
ULONG ulPCIE_Sclk;
} ATOM_Polaris10_PCIE_Record;
typedef struct _ATOM_Polaris10_PCIE_Table {
UCHAR ucRevId;
UCHAR ucNumEntries; /* Number of entries. */
ATOM_Polaris10_PCIE_Record entries[1]; /* Dynamically allocate entries. */
} ATOM_Polaris10_PCIE_Table;
typedef struct _ATOM_Tonga_MM_Dependency_Record {
UCHAR ucVddcInd; /* VDDC voltage */
USHORT usVddgfxOffset; /* Offset relative to VDDC voltage */
ULONG ulDClk; /* UVD D-clock */
ULONG ulVClk; /* UVD V-clock */
ULONG ulEClk; /* VCE clock */
ULONG ulAClk; /* ACP clock */
ULONG ulSAMUClk; /* SAMU clock */
} ATOM_Tonga_MM_Dependency_Record;
typedef struct _ATOM_Tonga_MM_Dependency_Table {
UCHAR ucRevId;
UCHAR ucNumEntries; /* Number of entries. */
ATOM_Tonga_MM_Dependency_Record entries[1]; /* Dynamically allocate entries. */
} ATOM_Tonga_MM_Dependency_Table;
typedef struct _ATOM_Tonga_Voltage_Lookup_Record {
USHORT usVdd; /* Base voltage */
USHORT usCACLow;
USHORT usCACMid;
USHORT usCACHigh;
} ATOM_Tonga_Voltage_Lookup_Record;
typedef struct _ATOM_Tonga_Voltage_Lookup_Table {
UCHAR ucRevId;
UCHAR ucNumEntries; /* Number of entries. */
ATOM_Tonga_Voltage_Lookup_Record entries[1]; /* Dynamically allocate entries. */
} ATOM_Tonga_Voltage_Lookup_Table;
typedef struct _ATOM_Tonga_Fan_Table {
UCHAR ucRevId; /* Change this if the table format changes or version changes so that the other fields are not the same. */
UCHAR ucTHyst; /* Temperature hysteresis. Integer. */
USHORT usTMin; /* The temperature, in 0.01 centigrades, below which we just run at a minimal PWM. */
USHORT usTMed; /* The middle temperature where we change slopes. */
USHORT usTHigh; /* The high point above TMed for adjusting the second slope. */
USHORT usPWMMin; /* The minimum PWM value in percent (0.01% increments). */
USHORT usPWMMed; /* The PWM value (in percent) at TMed. */
USHORT usPWMHigh; /* The PWM value at THigh. */
USHORT usTMax; /* The max temperature */
UCHAR ucFanControlMode; /* Legacy or Fuzzy Fan mode */
USHORT usFanPWMMax; /* Maximum allowed fan power in percent */
USHORT usFanOutputSensitivity; /* Sensitivity of fan reaction to temepature changes */
USHORT usFanRPMMax; /* The default value in RPM */
ULONG ulMinFanSCLKAcousticLimit; /* Minimum Fan Controller SCLK Frequency Acoustic Limit. */
UCHAR ucTargetTemperature; /* Advanced fan controller target temperature. */
UCHAR ucMinimumPWMLimit; /* The minimum PWM that the advanced fan controller can set. This should be set to the highest PWM that will run the fan at its lowest RPM. */
USHORT usReserved;
} ATOM_Tonga_Fan_Table;
typedef struct _ATOM_Fiji_Fan_Table {
UCHAR ucRevId; /* Change this if the table format changes or version changes so that the other fields are not the same. */
UCHAR ucTHyst; /* Temperature hysteresis. Integer. */
USHORT usTMin; /* The temperature, in 0.01 centigrades, below which we just run at a minimal PWM. */
USHORT usTMed; /* The middle temperature where we change slopes. */
USHORT usTHigh; /* The high point above TMed for adjusting the second slope. */
USHORT usPWMMin; /* The minimum PWM value in percent (0.01% increments). */
USHORT usPWMMed; /* The PWM value (in percent) at TMed. */
USHORT usPWMHigh; /* The PWM value at THigh. */
USHORT usTMax; /* The max temperature */
UCHAR ucFanControlMode; /* Legacy or Fuzzy Fan mode */
USHORT usFanPWMMax; /* Maximum allowed fan power in percent */
USHORT usFanOutputSensitivity; /* Sensitivity of fan reaction to temepature changes */
USHORT usFanRPMMax; /* The default value in RPM */
ULONG ulMinFanSCLKAcousticLimit; /* Minimum Fan Controller SCLK Frequency Acoustic Limit. */
UCHAR ucTargetTemperature; /* Advanced fan controller target temperature. */
UCHAR ucMinimumPWMLimit; /* The minimum PWM that the advanced fan controller can set. This should be set to the highest PWM that will run the fan at its lowest RPM. */
USHORT usFanGainEdge;
USHORT usFanGainHotspot;
USHORT usFanGainLiquid;
USHORT usFanGainVrVddc;
USHORT usFanGainVrMvdd;
USHORT usFanGainPlx;
USHORT usFanGainHbm;
USHORT usReserved;
} ATOM_Fiji_Fan_Table;
typedef struct _ATOM_Tonga_Thermal_Controller {
UCHAR ucRevId;
UCHAR ucType; /* one of ATOM_TONGA_PP_THERMALCONTROLLER_* */
UCHAR ucI2cLine; /* as interpreted by DAL I2C */
UCHAR ucI2cAddress;
UCHAR ucFanParameters; /* Fan Control Parameters. */
UCHAR ucFanMinRPM; /* Fan Minimum RPM (hundreds) -- for display purposes only. */
UCHAR ucFanMaxRPM; /* Fan Maximum RPM (hundreds) -- for display purposes only. */
UCHAR ucReserved;
UCHAR ucFlags; /* to be defined */
} ATOM_Tonga_Thermal_Controller;
typedef struct _ATOM_Tonga_VCE_State_Record {
UCHAR ucVCEClockIndex; /*index into usVCEDependencyTableOffset of 'ATOM_Tonga_MM_Dependency_Table' type */
UCHAR ucFlag; /* 2 bits indicates memory p-states */
UCHAR ucSCLKIndex; /*index into ATOM_Tonga_SCLK_Dependency_Table */
UCHAR ucMCLKIndex; /*index into ATOM_Tonga_MCLK_Dependency_Table */
} ATOM_Tonga_VCE_State_Record;
typedef struct _ATOM_Tonga_VCE_State_Table {
UCHAR ucRevId;
UCHAR ucNumEntries;
ATOM_Tonga_VCE_State_Record entries[1];
} ATOM_Tonga_VCE_State_Table;
typedef struct _ATOM_Tonga_PowerTune_Table {
UCHAR ucRevId;
USHORT usTDP;
USHORT usConfigurableTDP;
USHORT usTDC;
USHORT usBatteryPowerLimit;
USHORT usSmallPowerLimit;
USHORT usLowCACLeakage;
USHORT usHighCACLeakage;
USHORT usMaximumPowerDeliveryLimit;
USHORT usTjMax;
USHORT usPowerTuneDataSetID;
USHORT usEDCLimit;
USHORT usSoftwareShutdownTemp;
USHORT usClockStretchAmount;
USHORT usReserve[2];
} ATOM_Tonga_PowerTune_Table;
typedef struct _ATOM_Fiji_PowerTune_Table {
UCHAR ucRevId;
USHORT usTDP;
USHORT usConfigurableTDP;
USHORT usTDC;
USHORT usBatteryPowerLimit;
USHORT usSmallPowerLimit;
USHORT usLowCACLeakage;
USHORT usHighCACLeakage;
USHORT usMaximumPowerDeliveryLimit;
USHORT usTjMax; /* For Fiji, this is also usTemperatureLimitEdge; */
USHORT usPowerTuneDataSetID;
USHORT usEDCLimit;
USHORT usSoftwareShutdownTemp;
USHORT usClockStretchAmount;
USHORT usTemperatureLimitHotspot; /*The following are added for Fiji */
USHORT usTemperatureLimitLiquid1;
USHORT usTemperatureLimitLiquid2;
USHORT usTemperatureLimitVrVddc;
USHORT usTemperatureLimitVrMvdd;
USHORT usTemperatureLimitPlx;
UCHAR ucLiquid1_I2C_address; /*Liquid */
UCHAR ucLiquid2_I2C_address;
UCHAR ucLiquid_I2C_Line;
UCHAR ucVr_I2C_address; /*VR */
UCHAR ucVr_I2C_Line;
UCHAR ucPlx_I2C_address; /*PLX */
UCHAR ucPlx_I2C_Line;
USHORT usReserved;
} ATOM_Fiji_PowerTune_Table;
#define ATOM_PPM_A_A 1
#define ATOM_PPM_A_I 2
typedef struct _ATOM_Tonga_PPM_Table {
UCHAR ucRevId;
UCHAR ucPpmDesign; /*A+I or A+A */
USHORT usCpuCoreNumber;
ULONG ulPlatformTDP;
ULONG ulSmallACPlatformTDP;
ULONG ulPlatformTDC;
ULONG ulSmallACPlatformTDC;
ULONG ulApuTDP;
ULONG ulDGpuTDP;
ULONG ulDGpuUlvPower;
ULONG ulTjmax;
} ATOM_Tonga_PPM_Table;
typedef struct _ATOM_Tonga_Hard_Limit_Record {
ULONG ulSCLKLimit;
ULONG ulMCLKLimit;
USHORT usVddcLimit;
USHORT usVddciLimit;
USHORT usVddgfxLimit;
} ATOM_Tonga_Hard_Limit_Record;
typedef struct _ATOM_Tonga_Hard_Limit_Table {
UCHAR ucRevId;
UCHAR ucNumEntries;
ATOM_Tonga_Hard_Limit_Record entries[1];
} ATOM_Tonga_Hard_Limit_Table;
typedef struct _ATOM_Tonga_GPIO_Table {
UCHAR ucRevId;
UCHAR ucVRHotTriggeredSclkDpmIndex; /* If VRHot signal is triggered SCLK will be limited to this DPM level */
UCHAR ucReserve[5];
} ATOM_Tonga_GPIO_Table;
typedef struct _PPTable_Generic_SubTable_Header {
UCHAR ucRevId;
} PPTable_Generic_SubTable_Header;
#pragma pack(pop)
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,35 @@
/*
* Copyright 2015 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.
*
*/
#ifndef _PROCESSPPTABLES_V1_0_H
#define _PROCESSPPTABLES_V1_0_H
#include "hwmgr.h"
extern const struct pp_table_func pptable_v1_0_funcs;
extern int get_number_of_powerplay_table_entries_v1_0(struct pp_hwmgr *hwmgr);
extern int get_powerplay_table_entry_v1_0(struct pp_hwmgr *hwmgr, uint32_t entry_index,
struct pp_power_state *power_state, int (*call_back_func)(struct pp_hwmgr *, void *,
struct pp_power_state *, void *, uint32_t));
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,50 @@
/*
* Copyright 2015 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.
* Interface Functions related to the BIOS PowerPlay Tables.
*
*/
#ifndef PROCESSPPTABLES_H
#define PROCESSPPTABLES_H
struct pp_hwmgr;
struct pp_power_state;
struct pp_hw_power_state;
extern const struct pp_table_func pptable_funcs;
typedef int (*pp_tables_hw_clock_info_callback)(struct pp_hwmgr *hwmgr,
struct pp_hw_power_state *hw_ps,
unsigned int index,
const void *clock_info);
int pp_tables_get_num_of_entries(struct pp_hwmgr *hwmgr,
unsigned long *num_of_entries);
int pp_tables_get_entry(struct pp_hwmgr *hwmgr,
unsigned long entry_index,
struct pp_power_state *ps,
pp_tables_hw_clock_info_callback func);
int pp_tables_get_response_times(struct pp_hwmgr *hwmgr,
uint32_t *vol_rep_time, uint32_t *bb_rep_time);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,321 @@
/*
* Copyright 2017 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.
*
*/
#ifndef SMU10_HWMGR_H
#define SMU10_HWMGR_H
#include "hwmgr.h"
#include "smu10_inc.h"
#include "smu10_driver_if.h"
#include "rv_ppsmc.h"
#define SMU10_MAX_HARDWARE_POWERLEVELS 8
#define SMU10_DYNCLK_NUMBER_OF_TREND_COEFFICIENTS 15
#define DPMFlags_SCLK_Enabled 0x00000001
#define DPMFlags_UVD_Enabled 0x00000002
#define DPMFlags_VCE_Enabled 0x00000004
#define DPMFlags_ACP_Enabled 0x00000008
#define DPMFlags_ForceHighestValid 0x40000000
/* Do not change the following, it is also defined in SMU8.h */
#define SMU_EnabledFeatureScoreboard_AcpDpmOn 0x00000001
#define SMU_EnabledFeatureScoreboard_SclkDpmOn 0x00200000
#define SMU_EnabledFeatureScoreboard_UvdDpmOn 0x01000000
#define SMU_EnabledFeatureScoreboard_VceDpmOn 0x02000000
#define SMU_PHYID_SHIFT 8
#define SMU10_PCIE_POWERGATING_TARGET_GFX 0
#define SMU10_PCIE_POWERGATING_TARGET_DDI 1
#define SMU10_PCIE_POWERGATING_TARGET_PLLCASCADE 2
#define SMU10_PCIE_POWERGATING_TARGET_PHY 3
enum VQ_TYPE {
CLOCK_TYPE_DCLK = 0L,
CLOCK_TYPE_ECLK,
CLOCK_TYPE_SCLK,
CLOCK_TYPE_CCLK,
VQ_GFX_CU
};
#define SUSTAINABLE_SCLK_MASK 0x00ffffff
#define SUSTAINABLE_SCLK_SHIFT 0
#define SUSTAINABLE_CU_MASK 0xff000000
#define SUSTAINABLE_CU_SHIFT 24
struct smu10_dpm_entry {
uint32_t soft_min_clk;
uint32_t hard_min_clk;
uint32_t soft_max_clk;
uint32_t hard_max_clk;
};
struct smu10_power_level {
uint32_t engine_clock;
uint8_t vddc_index;
uint8_t ds_divider_index;
uint8_t ss_divider_index;
uint8_t allow_gnb_slow;
uint8_t force_nbp_state;
uint8_t display_wm;
uint8_t vce_wm;
uint8_t num_simd_to_powerdown;
uint8_t hysteresis_up;
uint8_t rsv[3];
};
/*used for the nbpsFlags field in smu10_power state*/
#define SMU10_POWERSTATE_FLAGS_NBPS_FORCEHIGH (1<<0)
#define SMU10_POWERSTATE_FLAGS_NBPS_LOCKTOHIGH (1<<1)
#define SMU10_POWERSTATE_FLAGS_NBPS_LOCKTOLOW (1<<2)
#define SMU10_POWERSTATE_FLAGS_BAPM_DISABLE (1<<0)
struct smu10_uvd_clocks {
uint32_t vclk;
uint32_t dclk;
uint32_t vclk_low_divider;
uint32_t vclk_high_divider;
uint32_t dclk_low_divider;
uint32_t dclk_high_divider;
};
struct pp_disable_nbpslo_flags {
union {
struct {
uint32_t entry : 1;
uint32_t display : 1;
uint32_t driver: 1;
uint32_t vce : 1;
uint32_t uvd : 1;
uint32_t acp : 1;
uint32_t reserved: 26;
} bits;
uint32_t u32All;
};
};
enum smu10_pstate_previous_action {
DO_NOTHING = 1,
FORCE_HIGH,
CANCEL_FORCE_HIGH
};
struct smu10_power_state {
unsigned int magic;
uint32_t level;
struct smu10_uvd_clocks uvd_clocks;
uint32_t evclk;
uint32_t ecclk;
uint32_t samclk;
uint32_t acpclk;
bool need_dfs_bypass;
uint32_t nbps_flags;
uint32_t bapm_flags;
uint8_t dpm0_pg_nbps_low;
uint8_t dpm0_pg_nbps_high;
uint8_t dpm_x_nbps_low;
uint8_t dpm_x_nbps_high;
enum smu10_pstate_previous_action action;
struct smu10_power_level levels[SMU10_MAX_HARDWARE_POWERLEVELS];
struct pp_disable_nbpslo_flags nbpslo_flags;
};
#define SMU10_NUM_NBPSTATES 4
#define SMU10_NUM_NBPMEMORYCLOCK 2
struct smu10_display_phy_info_entry {
uint8_t phy_present;
uint8_t active_lane_mapping;
uint8_t display_config_type;
uint8_t active_num_of_lanes;
};
#define SMU10_MAX_DISPLAYPHY_IDS 10
struct smu10_display_phy_info {
bool display_phy_access_initialized;
struct smu10_display_phy_info_entry entries[SMU10_MAX_DISPLAYPHY_IDS];
};
#define MAX_DISPLAY_CLOCK_LEVEL 8
struct smu10_system_info{
uint8_t htc_tmp_lmt;
uint8_t htc_hyst_lmt;
};
#define MAX_REGULAR_DPM_NUMBER 8
struct smu10_mclk_latency_entries {
uint32_t frequency;
uint32_t latency;
};
struct smu10_mclk_latency_table {
uint32_t count;
struct smu10_mclk_latency_entries entries[MAX_REGULAR_DPM_NUMBER];
};
struct smu10_clock_voltage_dependency_record {
uint32_t clk;
uint32_t vol;
};
struct smu10_voltage_dependency_table {
uint32_t count;
struct smu10_clock_voltage_dependency_record entries[];
};
struct smu10_clock_voltage_information {
struct smu10_voltage_dependency_table *vdd_dep_on_dcefclk;
struct smu10_voltage_dependency_table *vdd_dep_on_socclk;
struct smu10_voltage_dependency_table *vdd_dep_on_fclk;
struct smu10_voltage_dependency_table *vdd_dep_on_mclk;
struct smu10_voltage_dependency_table *vdd_dep_on_dispclk;
struct smu10_voltage_dependency_table *vdd_dep_on_dppclk;
struct smu10_voltage_dependency_table *vdd_dep_on_phyclk;
};
struct smu10_hwmgr {
uint32_t disable_driver_thermal_policy;
uint32_t thermal_auto_throttling_treshold;
struct smu10_system_info sys_info;
struct smu10_mclk_latency_table mclk_latency_table;
uint32_t ddi_power_gating_disabled;
struct smu10_display_phy_info_entry display_phy_info;
uint32_t dce_slow_sclk_threshold;
bool disp_clk_bypass;
bool disp_clk_bypass_pending;
uint32_t bapm_enabled;
bool video_start;
bool battery_state;
uint32_t is_nb_dpm_enabled;
uint32_t is_voltage_island_enabled;
uint32_t disable_smu_acp_s3_handshake;
uint32_t disable_notify_smu_vpu_recovery;
bool in_vpu_recovery;
bool pg_acp_init;
uint8_t disp_config;
/* PowerTune */
uint32_t power_containment_features;
bool cac_enabled;
bool disable_uvd_power_tune_feature;
bool enable_bapm_feature;
bool enable_tdc_limit_feature;
/* SMC SRAM Address of firmware header tables */
uint32_t sram_end;
uint32_t dpm_table_start;
uint32_t soft_regs_start;
/* start of SMU7_Fusion_DpmTable */
uint8_t uvd_level_count;
uint8_t vce_level_count;
uint8_t acp_level_count;
uint8_t samu_level_count;
uint32_t fps_high_threshold;
uint32_t fps_low_threshold;
uint32_t dpm_flags;
struct smu10_dpm_entry sclk_dpm;
struct smu10_dpm_entry uvd_dpm;
struct smu10_dpm_entry vce_dpm;
struct smu10_dpm_entry acp_dpm;
bool acp_power_up_no_dsp;
uint32_t max_sclk_level;
uint32_t num_of_clk_entries;
/* CPU Power State */
uint32_t separation_time;
bool cc6_disable;
bool pstate_disable;
bool cc6_setting_changed;
uint32_t ulTotalActiveCUs;
bool isp_tileA_power_gated;
bool isp_tileB_power_gated;
uint32_t isp_actual_hard_min_freq;
uint32_t soc_actual_hard_min_freq;
uint32_t dcf_actual_hard_min_freq;
uint32_t f_actual_hard_min_freq;
uint32_t fabric_actual_soft_min_freq;
uint32_t vclk_soft_min;
uint32_t dclk_soft_min;
uint32_t gfx_actual_soft_min_freq;
uint32_t gfx_min_freq_limit;
uint32_t gfx_max_freq_limit;
bool vcn_power_gated;
bool vcn_dpg_mode;
bool gfx_off_controled_by_driver;
bool water_marks_exist;
Watermarks_t water_marks_table;
struct smu10_clock_voltage_information clock_vol_info;
DpmClocks_t clock_table;
uint32_t active_process_mask;
bool need_min_deep_sleep_dcefclk;
uint32_t deep_sleep_dcefclk;
uint32_t num_active_display;
};
struct pp_hwmgr;
int smu10_init_function_pointers(struct pp_hwmgr *hwmgr);
/* UMD PState SMU10 Msg Parameters in MHz */
#define SMU10_UMD_PSTATE_GFXCLK 700
#define SMU10_UMD_PSTATE_SOCCLK 626
#define SMU10_UMD_PSTATE_FCLK 933
#define SMU10_UMD_PSTATE_VCE 0x03C00320
#define SMU10_UMD_PSTATE_PEAK_SOCCLK 757
#define SMU10_UMD_PSTATE_PEAK_FCLK 1200
#define SMU10_UMD_PSTATE_MIN_FCLK 400
#define SMU10_UMD_PSTATE_MIN_SOCCLK 200
#define SMU10_UMD_PSTATE_MIN_VCE 0x0190012C
#endif

View File

@@ -0,0 +1,43 @@
/*
* 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.
*
*/
#ifndef SMU10_INC_H
#define SMU10_INC_H
#include "asic_reg/mp/mp_10_0_default.h"
#include "asic_reg/mp/mp_10_0_offset.h"
#include "asic_reg/mp/mp_10_0_sh_mask.h"
#include "asic_reg/nbio/nbio_7_0_default.h"
#include "asic_reg/nbio/nbio_7_0_offset.h"
#include "asic_reg/nbio/nbio_7_0_sh_mask.h"
#include "asic_reg/thm/thm_10_0_default.h"
#include "asic_reg/thm/thm_10_0_offset.h"
#include "asic_reg/thm/thm_10_0_sh_mask.h"
#define ixDDI_PHY_GEN_STATUS 0x3FCE8
#endif

View File

@@ -0,0 +1,91 @@
/*
* Copyright 2019 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 "smu7_baco.h"
#include "tonga_baco.h"
#include "fiji_baco.h"
#include "polaris_baco.h"
#include "ci_baco.h"
#include "bif/bif_5_0_d.h"
#include "bif/bif_5_0_sh_mask.h"
#include "smu/smu_7_1_2_d.h"
#include "smu/smu_7_1_2_sh_mask.h"
int smu7_baco_get_capability(struct pp_hwmgr *hwmgr, bool *cap)
{
struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev);
uint32_t reg;
*cap = false;
if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_BACO))
return 0;
reg = RREG32(mmCC_BIF_BX_FUSESTRAP0);
if (reg & CC_BIF_BX_FUSESTRAP0__STRAP_BIF_PX_CAPABLE_MASK)
*cap = true;
return 0;
}
int smu7_baco_get_state(struct pp_hwmgr *hwmgr, enum BACO_STATE *state)
{
struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev);
uint32_t reg;
reg = RREG32(mmBACO_CNTL);
if (reg & BACO_CNTL__BACO_MODE_MASK)
/* gfx has already entered BACO state */
*state = BACO_STATE_IN;
else
*state = BACO_STATE_OUT;
return 0;
}
int smu7_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state)
{
struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev);
switch (adev->asic_type) {
case CHIP_TOPAZ:
case CHIP_TONGA:
return tonga_baco_set_state(hwmgr, state);
case CHIP_FIJI:
return fiji_baco_set_state(hwmgr, state);
case CHIP_POLARIS10:
case CHIP_POLARIS11:
case CHIP_POLARIS12:
case CHIP_VEGAM:
return polaris_baco_set_state(hwmgr, state);
#ifdef CONFIG_DRM_AMDGPU_CIK
case CHIP_BONAIRE:
case CHIP_HAWAII:
return ci_baco_set_state(hwmgr, state);
#endif
default:
return -EINVAL;
}
}

View File

@@ -0,0 +1,32 @@
/*
* Copyright 2019 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.
*
*/
#ifndef __SMU7_BACO_H__
#define __SMU7_BACO_H__
#include "hwmgr.h"
#include "common_baco.h"
extern int smu7_baco_get_capability(struct pp_hwmgr *hwmgr, bool *cap);
extern int smu7_baco_get_state(struct pp_hwmgr *hwmgr, enum BACO_STATE *state);
extern int smu7_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state);
#endif

View File

@@ -0,0 +1,437 @@
/*
* 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 "smu7_hwmgr.h"
#include "smu7_clockpowergating.h"
#include "smu7_common.h"
static int smu7_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable)
{
return smum_send_msg_to_smc(hwmgr, enable ?
PPSMC_MSG_UVDDPM_Enable :
PPSMC_MSG_UVDDPM_Disable,
NULL);
}
static int smu7_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable)
{
return smum_send_msg_to_smc(hwmgr, enable ?
PPSMC_MSG_VCEDPM_Enable :
PPSMC_MSG_VCEDPM_Disable,
NULL);
}
static int smu7_update_uvd_dpm(struct pp_hwmgr *hwmgr, bool bgate)
{
if (!bgate)
smum_update_smc_table(hwmgr, SMU_UVD_TABLE);
return smu7_enable_disable_uvd_dpm(hwmgr, !bgate);
}
static int smu7_update_vce_dpm(struct pp_hwmgr *hwmgr, bool bgate)
{
if (!bgate)
smum_update_smc_table(hwmgr, SMU_VCE_TABLE);
return smu7_enable_disable_vce_dpm(hwmgr, !bgate);
}
int smu7_powerdown_uvd(struct pp_hwmgr *hwmgr)
{
if (phm_cf_want_uvd_power_gating(hwmgr))
return smum_send_msg_to_smc(hwmgr,
PPSMC_MSG_UVDPowerOFF,
NULL);
return 0;
}
static int smu7_powerup_uvd(struct pp_hwmgr *hwmgr)
{
if (phm_cf_want_uvd_power_gating(hwmgr)) {
if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_UVDDynamicPowerGating)) {
return smum_send_msg_to_smc_with_parameter(hwmgr,
PPSMC_MSG_UVDPowerON, 1, NULL);
} else {
return smum_send_msg_to_smc_with_parameter(hwmgr,
PPSMC_MSG_UVDPowerON, 0, NULL);
}
}
return 0;
}
static int smu7_powerdown_vce(struct pp_hwmgr *hwmgr)
{
if (phm_cf_want_vce_power_gating(hwmgr))
return smum_send_msg_to_smc(hwmgr,
PPSMC_MSG_VCEPowerOFF,
NULL);
return 0;
}
static int smu7_powerup_vce(struct pp_hwmgr *hwmgr)
{
if (phm_cf_want_vce_power_gating(hwmgr))
return smum_send_msg_to_smc(hwmgr,
PPSMC_MSG_VCEPowerON,
NULL);
return 0;
}
int smu7_disable_clock_power_gating(struct pp_hwmgr *hwmgr)
{
struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
data->uvd_power_gated = false;
data->vce_power_gated = false;
smu7_powerup_uvd(hwmgr);
smu7_powerup_vce(hwmgr);
return 0;
}
void smu7_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate)
{
struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
data->uvd_power_gated = bgate;
if (bgate) {
amdgpu_device_ip_set_powergating_state(hwmgr->adev,
AMD_IP_BLOCK_TYPE_UVD,
AMD_PG_STATE_GATE);
amdgpu_device_ip_set_clockgating_state(hwmgr->adev,
AMD_IP_BLOCK_TYPE_UVD,
AMD_CG_STATE_GATE);
smu7_update_uvd_dpm(hwmgr, true);
smu7_powerdown_uvd(hwmgr);
} else {
smu7_powerup_uvd(hwmgr);
amdgpu_device_ip_set_clockgating_state(hwmgr->adev,
AMD_IP_BLOCK_TYPE_UVD,
AMD_CG_STATE_UNGATE);
amdgpu_device_ip_set_powergating_state(hwmgr->adev,
AMD_IP_BLOCK_TYPE_UVD,
AMD_PG_STATE_UNGATE);
smu7_update_uvd_dpm(hwmgr, false);
}
}
void smu7_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate)
{
struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
data->vce_power_gated = bgate;
if (bgate) {
amdgpu_device_ip_set_powergating_state(hwmgr->adev,
AMD_IP_BLOCK_TYPE_VCE,
AMD_PG_STATE_GATE);
amdgpu_device_ip_set_clockgating_state(hwmgr->adev,
AMD_IP_BLOCK_TYPE_VCE,
AMD_CG_STATE_GATE);
smu7_update_vce_dpm(hwmgr, true);
smu7_powerdown_vce(hwmgr);
} else {
smu7_powerup_vce(hwmgr);
amdgpu_device_ip_set_clockgating_state(hwmgr->adev,
AMD_IP_BLOCK_TYPE_VCE,
AMD_CG_STATE_UNGATE);
amdgpu_device_ip_set_powergating_state(hwmgr->adev,
AMD_IP_BLOCK_TYPE_VCE,
AMD_PG_STATE_UNGATE);
smu7_update_vce_dpm(hwmgr, false);
}
}
int smu7_update_clock_gatings(struct pp_hwmgr *hwmgr,
const uint32_t *msg_id)
{
PPSMC_Msg msg;
uint32_t value;
if (!(hwmgr->feature_mask & PP_ENABLE_GFX_CG_THRU_SMU))
return 0;
switch ((*msg_id & PP_GROUP_MASK) >> PP_GROUP_SHIFT) {
case PP_GROUP_GFX:
switch ((*msg_id & PP_BLOCK_MASK) >> PP_BLOCK_SHIFT) {
case PP_BLOCK_GFX_CG:
if (PP_STATE_SUPPORT_CG & *msg_id) {
msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
PPSMC_MSG_EnableClockGatingFeature :
PPSMC_MSG_DisableClockGatingFeature;
value = CG_GFX_CGCG_MASK;
if (smum_send_msg_to_smc_with_parameter(
hwmgr, msg, value, NULL))
return -EINVAL;
}
if (PP_STATE_SUPPORT_LS & *msg_id) {
msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS
? PPSMC_MSG_EnableClockGatingFeature
: PPSMC_MSG_DisableClockGatingFeature;
value = CG_GFX_CGLS_MASK;
if (smum_send_msg_to_smc_with_parameter(
hwmgr, msg, value, NULL))
return -EINVAL;
}
break;
case PP_BLOCK_GFX_3D:
if (PP_STATE_SUPPORT_CG & *msg_id) {
msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
PPSMC_MSG_EnableClockGatingFeature :
PPSMC_MSG_DisableClockGatingFeature;
value = CG_GFX_3DCG_MASK;
if (smum_send_msg_to_smc_with_parameter(
hwmgr, msg, value, NULL))
return -EINVAL;
}
if (PP_STATE_SUPPORT_LS & *msg_id) {
msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
PPSMC_MSG_EnableClockGatingFeature :
PPSMC_MSG_DisableClockGatingFeature;
value = CG_GFX_3DLS_MASK;
if (smum_send_msg_to_smc_with_parameter(
hwmgr, msg, value, NULL))
return -EINVAL;
}
break;
case PP_BLOCK_GFX_RLC:
if (PP_STATE_SUPPORT_LS & *msg_id) {
msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
PPSMC_MSG_EnableClockGatingFeature :
PPSMC_MSG_DisableClockGatingFeature;
value = CG_GFX_RLC_LS_MASK;
if (smum_send_msg_to_smc_with_parameter(
hwmgr, msg, value, NULL))
return -EINVAL;
}
break;
case PP_BLOCK_GFX_CP:
if (PP_STATE_SUPPORT_LS & *msg_id) {
msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
PPSMC_MSG_EnableClockGatingFeature :
PPSMC_MSG_DisableClockGatingFeature;
value = CG_GFX_CP_LS_MASK;
if (smum_send_msg_to_smc_with_parameter(
hwmgr, msg, value, NULL))
return -EINVAL;
}
break;
case PP_BLOCK_GFX_MG:
if (PP_STATE_SUPPORT_CG & *msg_id) {
msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
PPSMC_MSG_EnableClockGatingFeature :
PPSMC_MSG_DisableClockGatingFeature;
value = (CG_CPF_MGCG_MASK | CG_RLC_MGCG_MASK |
CG_GFX_OTHERS_MGCG_MASK);
if (smum_send_msg_to_smc_with_parameter(
hwmgr, msg, value, NULL))
return -EINVAL;
}
break;
default:
return -EINVAL;
}
break;
case PP_GROUP_SYS:
switch ((*msg_id & PP_BLOCK_MASK) >> PP_BLOCK_SHIFT) {
case PP_BLOCK_SYS_BIF:
if (PP_STATE_SUPPORT_CG & *msg_id) {
msg = (*msg_id & PP_STATE_MASK) & PP_STATE_CG ?
PPSMC_MSG_EnableClockGatingFeature :
PPSMC_MSG_DisableClockGatingFeature;
value = CG_SYS_BIF_MGCG_MASK;
if (smum_send_msg_to_smc_with_parameter(
hwmgr, msg, value, NULL))
return -EINVAL;
}
if (PP_STATE_SUPPORT_LS & *msg_id) {
msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
PPSMC_MSG_EnableClockGatingFeature :
PPSMC_MSG_DisableClockGatingFeature;
value = CG_SYS_BIF_MGLS_MASK;
if (smum_send_msg_to_smc_with_parameter(
hwmgr, msg, value, NULL))
return -EINVAL;
}
break;
case PP_BLOCK_SYS_MC:
if (PP_STATE_SUPPORT_CG & *msg_id) {
msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
PPSMC_MSG_EnableClockGatingFeature :
PPSMC_MSG_DisableClockGatingFeature;
value = CG_SYS_MC_MGCG_MASK;
if (smum_send_msg_to_smc_with_parameter(
hwmgr, msg, value, NULL))
return -EINVAL;
}
if (PP_STATE_SUPPORT_LS & *msg_id) {
msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
PPSMC_MSG_EnableClockGatingFeature :
PPSMC_MSG_DisableClockGatingFeature;
value = CG_SYS_MC_MGLS_MASK;
if (smum_send_msg_to_smc_with_parameter(
hwmgr, msg, value, NULL))
return -EINVAL;
}
break;
case PP_BLOCK_SYS_DRM:
if (PP_STATE_SUPPORT_CG & *msg_id) {
msg = (*msg_id & PP_STATE_MASK) & PP_STATE_CG ?
PPSMC_MSG_EnableClockGatingFeature :
PPSMC_MSG_DisableClockGatingFeature;
value = CG_SYS_DRM_MGCG_MASK;
if (smum_send_msg_to_smc_with_parameter(
hwmgr, msg, value, NULL))
return -EINVAL;
}
if (PP_STATE_SUPPORT_LS & *msg_id) {
msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
PPSMC_MSG_EnableClockGatingFeature :
PPSMC_MSG_DisableClockGatingFeature;
value = CG_SYS_DRM_MGLS_MASK;
if (smum_send_msg_to_smc_with_parameter(
hwmgr, msg, value, NULL))
return -EINVAL;
}
break;
case PP_BLOCK_SYS_HDP:
if (PP_STATE_SUPPORT_CG & *msg_id) {
msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
PPSMC_MSG_EnableClockGatingFeature :
PPSMC_MSG_DisableClockGatingFeature;
value = CG_SYS_HDP_MGCG_MASK;
if (smum_send_msg_to_smc_with_parameter(
hwmgr, msg, value, NULL))
return -EINVAL;
}
if (PP_STATE_SUPPORT_LS & *msg_id) {
msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
PPSMC_MSG_EnableClockGatingFeature :
PPSMC_MSG_DisableClockGatingFeature;
value = CG_SYS_HDP_MGLS_MASK;
if (smum_send_msg_to_smc_with_parameter(
hwmgr, msg, value, NULL))
return -EINVAL;
}
break;
case PP_BLOCK_SYS_SDMA:
if (PP_STATE_SUPPORT_CG & *msg_id) {
msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
PPSMC_MSG_EnableClockGatingFeature :
PPSMC_MSG_DisableClockGatingFeature;
value = CG_SYS_SDMA_MGCG_MASK;
if (smum_send_msg_to_smc_with_parameter(
hwmgr, msg, value, NULL))
return -EINVAL;
}
if (PP_STATE_SUPPORT_LS & *msg_id) {
msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
PPSMC_MSG_EnableClockGatingFeature :
PPSMC_MSG_DisableClockGatingFeature;
value = CG_SYS_SDMA_MGLS_MASK;
if (smum_send_msg_to_smc_with_parameter(
hwmgr, msg, value, NULL))
return -EINVAL;
}
break;
case PP_BLOCK_SYS_ROM:
if (PP_STATE_SUPPORT_CG & *msg_id) {
msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
PPSMC_MSG_EnableClockGatingFeature :
PPSMC_MSG_DisableClockGatingFeature;
value = CG_SYS_ROM_MASK;
if (smum_send_msg_to_smc_with_parameter(
hwmgr, msg, value, NULL))
return -EINVAL;
}
break;
default:
return -EINVAL;
}
break;
default:
return -EINVAL;
}
return 0;
}
/* This function is for Polaris11 only for now,
* Powerplay will only control the static per CU Power Gating.
* Dynamic per CU Power Gating will be done in gfx.
*/
int smu7_powergate_gfx(struct pp_hwmgr *hwmgr, bool enable)
{
struct amdgpu_device *adev = hwmgr->adev;
if (enable)
return smum_send_msg_to_smc_with_parameter(hwmgr,
PPSMC_MSG_GFX_CU_PG_ENABLE,
adev->gfx.cu_info.number,
NULL);
else
return smum_send_msg_to_smc(hwmgr,
PPSMC_MSG_GFX_CU_PG_DISABLE,
NULL);
}

View File

@@ -0,0 +1,38 @@
/*
* 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.
*
*/
#ifndef _SMU7_CLOCK_POWER_GATING_H_
#define _SMU7_CLOCK_POWER_GATING_H_
#include "smu7_hwmgr.h"
void smu7_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate);
void smu7_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate);
int smu7_powerdown_uvd(struct pp_hwmgr *hwmgr);
int smu7_powergate_acp(struct pp_hwmgr *hwmgr, bool bgate);
int smu7_disable_clock_power_gating(struct pp_hwmgr *hwmgr);
int smu7_update_clock_gatings(struct pp_hwmgr *hwmgr,
const uint32_t *msg_id);
int smu7_powergate_gfx(struct pp_hwmgr *hwmgr, bool enable);
#endif

View File

@@ -0,0 +1,55 @@
/*
* Copyright 2015 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.
*
*/
#ifndef _SMU7_DYN_DEFAULTS_H
#define _SMU7_DYN_DEFAULTS_H
/* We need to fill in the default values */
#define SMU7_VOTINGRIGHTSCLIENTS_DFLT0 0x3FFFC102
#define SMU7_VOTINGRIGHTSCLIENTS_DFLT1 0x000400
#define SMU7_VOTINGRIGHTSCLIENTS_DFLT2 0xC00080
#define SMU7_VOTINGRIGHTSCLIENTS_DFLT3 0xC00200
#define SMU7_VOTINGRIGHTSCLIENTS_DFLT4 0xC01680
#define SMU7_VOTINGRIGHTSCLIENTS_DFLT5 0xC00033
#define SMU7_VOTINGRIGHTSCLIENTS_DFLT6 0xC00033
#define SMU7_VOTINGRIGHTSCLIENTS_DFLT7 0x3FFFC000
#define SMU7_THERMALPROTECTCOUNTER_DFLT 0x200
#define SMU7_STATICSCREENTHRESHOLDUNIT_DFLT 0
#define SMU7_STATICSCREENTHRESHOLD_DFLT 0x00C8
#define SMU7_GFXIDLECLOCKSTOPTHRESHOLD_DFLT 0x200
#define SMU7_REFERENCEDIVIDER_DFLT 4
#define SMU7_ULVVOLTAGECHANGEDELAY_DFLT 1687
#define SMU7_CGULVPARAMETER_DFLT 0x00040035
#define SMU7_CGULVCONTROL_DFLT 0x00007450
#define SMU7_TARGETACTIVITY_DFLT 50
#define SMU7_MCLK_TARGETACTIVITY_DFLT 10
#define SMU7_SCLK_TARGETACTIVITY_DFLT 30
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,368 @@
/*
* Copyright 2015 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.
*
*/
#ifndef _SMU7_HWMGR_H
#define _SMU7_HWMGR_H
#include "hwmgr.h"
#include "ppatomctrl.h"
#define SMU7_MAX_HARDWARE_POWERLEVELS 2
#define SMU7_VOLTAGE_CONTROL_NONE 0x0
#define SMU7_VOLTAGE_CONTROL_BY_GPIO 0x1
#define SMU7_VOLTAGE_CONTROL_BY_SVID2 0x2
#define SMU7_VOLTAGE_CONTROL_MERGED 0x3
enum gpu_pt_config_reg_type {
GPU_CONFIGREG_MMR = 0,
GPU_CONFIGREG_SMC_IND,
GPU_CONFIGREG_DIDT_IND,
GPU_CONFIGREG_GC_CAC_IND,
GPU_CONFIGREG_CACHE,
GPU_CONFIGREG_MAX
};
struct gpu_pt_config_reg {
uint32_t offset;
uint32_t mask;
uint32_t shift;
uint32_t value;
enum gpu_pt_config_reg_type type;
};
struct smu7_performance_level {
uint32_t memory_clock;
uint32_t engine_clock;
uint16_t pcie_gen;
uint16_t pcie_lane;
};
struct smu7_thermal_temperature_setting {
long temperature_low;
long temperature_high;
long temperature_shutdown;
};
struct smu7_uvd_clocks {
uint32_t vclk;
uint32_t dclk;
};
struct smu7_vce_clocks {
uint32_t evclk;
uint32_t ecclk;
};
struct smu7_power_state {
uint32_t magic;
struct smu7_uvd_clocks uvd_clks;
struct smu7_vce_clocks vce_clks;
uint32_t sam_clk;
uint16_t performance_level_count;
bool dc_compatible;
uint32_t sclk_threshold;
struct smu7_performance_level performance_levels[SMU7_MAX_HARDWARE_POWERLEVELS];
};
struct smu7_dpm_level {
bool enabled;
uint32_t value;
uint32_t param1;
};
#define SMU7_MAX_DEEPSLEEP_DIVIDER_ID 5
#define MAX_REGULAR_DPM_NUMBER 8
#define SMU7_MINIMUM_ENGINE_CLOCK 2500
struct smu7_single_dpm_table {
uint32_t count;
struct smu7_dpm_level dpm_levels[MAX_REGULAR_DPM_NUMBER];
};
struct smu7_dpm_table {
struct smu7_single_dpm_table sclk_table;
struct smu7_single_dpm_table mclk_table;
struct smu7_single_dpm_table pcie_speed_table;
struct smu7_single_dpm_table vddc_table;
struct smu7_single_dpm_table vddci_table;
struct smu7_single_dpm_table mvdd_table;
};
struct smu7_clock_registers {
uint32_t vCG_SPLL_FUNC_CNTL;
uint32_t vCG_SPLL_FUNC_CNTL_2;
uint32_t vCG_SPLL_FUNC_CNTL_3;
uint32_t vCG_SPLL_FUNC_CNTL_4;
uint32_t vCG_SPLL_SPREAD_SPECTRUM;
uint32_t vCG_SPLL_SPREAD_SPECTRUM_2;
uint32_t vDLL_CNTL;
uint32_t vMCLK_PWRMGT_CNTL;
uint32_t vMPLL_AD_FUNC_CNTL;
uint32_t vMPLL_DQ_FUNC_CNTL;
uint32_t vMPLL_FUNC_CNTL;
uint32_t vMPLL_FUNC_CNTL_1;
uint32_t vMPLL_FUNC_CNTL_2;
uint32_t vMPLL_SS1;
uint32_t vMPLL_SS2;
};
#define DISABLE_MC_LOADMICROCODE 1
#define DISABLE_MC_CFGPROGRAMMING 2
struct smu7_voltage_smio_registers {
uint32_t vS0_VID_LOWER_SMIO_CNTL;
};
#define SMU7_MAX_LEAKAGE_COUNT 8
struct smu7_leakage_voltage {
uint16_t count;
uint16_t leakage_id[SMU7_MAX_LEAKAGE_COUNT];
uint16_t actual_voltage[SMU7_MAX_LEAKAGE_COUNT];
};
struct smu7_vbios_boot_state {
uint16_t mvdd_bootup_value;
uint16_t vddc_bootup_value;
uint16_t vddci_bootup_value;
uint16_t vddgfx_bootup_value;
uint32_t sclk_bootup_value;
uint32_t mclk_bootup_value;
uint16_t pcie_gen_bootup_value;
uint16_t pcie_lane_bootup_value;
};
struct smu7_display_timing {
uint32_t min_clock_in_sr;
uint32_t num_existing_displays;
uint32_t vrefresh;
};
struct smu7_dpmlevel_enable_mask {
uint32_t uvd_dpm_enable_mask;
uint32_t vce_dpm_enable_mask;
uint32_t acp_dpm_enable_mask;
uint32_t samu_dpm_enable_mask;
uint32_t sclk_dpm_enable_mask;
uint32_t mclk_dpm_enable_mask;
uint32_t pcie_dpm_enable_mask;
};
struct smu7_pcie_perf_range {
uint16_t max;
uint16_t min;
};
struct smu7_odn_clock_voltage_dependency_table {
uint32_t count;
phm_ppt_v1_clock_voltage_dependency_record entries[MAX_REGULAR_DPM_NUMBER];
};
struct smu7_odn_dpm_table {
struct phm_odn_clock_levels odn_core_clock_dpm_levels;
struct phm_odn_clock_levels odn_memory_clock_dpm_levels;
struct smu7_odn_clock_voltage_dependency_table vdd_dependency_on_sclk;
struct smu7_odn_clock_voltage_dependency_table vdd_dependency_on_mclk;
uint32_t odn_mclk_min_limit;
uint32_t min_vddc;
uint32_t max_vddc;
};
struct profile_mode_setting {
uint8_t bupdate_sclk;
uint8_t sclk_up_hyst;
uint8_t sclk_down_hyst;
uint16_t sclk_activity;
uint8_t bupdate_mclk;
uint8_t mclk_up_hyst;
uint8_t mclk_down_hyst;
uint16_t mclk_activity;
};
struct smu7_hwmgr {
struct smu7_dpm_table dpm_table;
struct smu7_dpm_table golden_dpm_table;
struct smu7_odn_dpm_table odn_dpm_table;
uint32_t voting_rights_clients[8];
uint32_t static_screen_threshold_unit;
uint32_t static_screen_threshold;
uint32_t voltage_control;
uint32_t vdd_gfx_control;
uint32_t vddc_vddgfx_delta;
uint32_t active_auto_throttle_sources;
struct smu7_clock_registers clock_registers;
bool is_memory_gddr5;
uint16_t acpi_vddc;
bool pspp_notify_required;
uint16_t force_pcie_gen;
uint16_t acpi_pcie_gen;
uint32_t pcie_gen_cap;
uint32_t pcie_lane_cap;
uint32_t pcie_spc_cap;
struct smu7_leakage_voltage vddc_leakage;
struct smu7_leakage_voltage vddci_leakage;
struct smu7_leakage_voltage vddcgfx_leakage;
uint32_t mvdd_control;
uint32_t vddc_mask_low;
uint32_t mvdd_mask_low;
uint16_t max_vddc_in_pptable;
uint16_t min_vddc_in_pptable;
uint16_t max_vddci_in_pptable;
uint16_t min_vddci_in_pptable;
bool is_uvd_enabled;
struct smu7_vbios_boot_state vbios_boot_state;
bool pcie_performance_request;
bool battery_state;
bool is_tlu_enabled;
bool disable_handshake;
bool smc_voltage_control_enabled;
bool vbi_time_out_support;
uint32_t soft_regs_start;
/* ---- Stuff originally coming from Evergreen ---- */
uint32_t vddci_control;
struct pp_atomctrl_voltage_table vddc_voltage_table;
struct pp_atomctrl_voltage_table vddci_voltage_table;
struct pp_atomctrl_voltage_table mvdd_voltage_table;
struct pp_atomctrl_voltage_table vddgfx_voltage_table;
uint32_t mgcg_cgtt_local2;
uint32_t mgcg_cgtt_local3;
uint32_t gpio_debug;
uint32_t mc_micro_code_feature;
uint32_t highest_mclk;
uint16_t acpi_vddci;
uint8_t mvdd_high_index;
uint8_t mvdd_low_index;
bool dll_default_on;
bool performance_request_registered;
/* ---- Low Power Features ---- */
bool ulv_supported;
/* ---- CAC Stuff ---- */
uint32_t cac_table_start;
bool cac_configuration_required;
bool driver_calculate_cac_leakage;
bool cac_enabled;
/* ---- DPM2 Parameters ---- */
uint32_t power_containment_features;
bool enable_dte_feature;
bool enable_tdc_limit_feature;
bool enable_pkg_pwr_tracking_feature;
bool disable_uvd_power_tune_feature;
uint32_t dte_tj_offset;
uint32_t fast_watermark_threshold;
/* ---- Phase Shedding ---- */
uint8_t vddc_phase_shed_control;
/* ---- DI/DT ---- */
struct smu7_display_timing display_timing;
/* ---- Thermal Temperature Setting ---- */
struct smu7_thermal_temperature_setting thermal_temp_setting;
struct smu7_dpmlevel_enable_mask dpm_level_enable_mask;
uint32_t need_update_smu7_dpm_table;
uint32_t sclk_dpm_key_disabled;
uint32_t mclk_dpm_key_disabled;
uint32_t pcie_dpm_key_disabled;
uint32_t min_engine_clocks;
struct smu7_pcie_perf_range pcie_gen_performance;
struct smu7_pcie_perf_range pcie_lane_performance;
struct smu7_pcie_perf_range pcie_gen_power_saving;
struct smu7_pcie_perf_range pcie_lane_power_saving;
bool use_pcie_performance_levels;
bool use_pcie_power_saving_levels;
uint32_t mclk_dpm0_activity_target;
uint32_t low_sclk_interrupt_threshold;
uint32_t last_mclk_dpm_enable_mask;
bool uvd_enabled;
/* ---- Power Gating States ---- */
bool uvd_power_gated;
bool vce_power_gated;
bool need_long_memory_training;
/* Application power optimization parameters */
bool update_up_hyst;
bool update_down_hyst;
uint32_t down_hyst;
uint32_t up_hyst;
uint32_t disable_dpm_mask;
bool apply_optimized_settings;
uint32_t avfs_vdroop_override_setting;
bool apply_avfs_cks_off_voltage;
uint32_t frame_time_x2;
uint16_t mem_latency_high;
uint16_t mem_latency_low;
uint32_t vr_config;
struct profile_mode_setting current_profile_setting;
};
/* To convert to Q8.8 format for firmware */
#define SMU7_Q88_FORMAT_CONVERSION_UNIT 256
enum SMU7_I2CLineID {
SMU7_I2CLineID_DDC1 = 0x90,
SMU7_I2CLineID_DDC2 = 0x91,
SMU7_I2CLineID_DDC3 = 0x92,
SMU7_I2CLineID_DDC4 = 0x93,
SMU7_I2CLineID_DDC5 = 0x94,
SMU7_I2CLineID_DDC6 = 0x95,
SMU7_I2CLineID_SCLSDA = 0x96,
SMU7_I2CLineID_DDCVGA = 0x97
};
#define SMU7_I2C_DDC1DATA 0
#define SMU7_I2C_DDC1CLK 1
#define SMU7_I2C_DDC2DATA 2
#define SMU7_I2C_DDC2CLK 3
#define SMU7_I2C_DDC3DATA 4
#define SMU7_I2C_DDC3CLK 5
#define SMU7_I2C_SDA 40
#define SMU7_I2C_SCL 41
#define SMU7_I2C_DDC4DATA 65
#define SMU7_I2C_DDC4CLK 66
#define SMU7_I2C_DDC5DATA 0x48
#define SMU7_I2C_DDC5CLK 0x49
#define SMU7_I2C_DDC6DATA 0x4a
#define SMU7_I2C_DDC6CLK 0x4b
#define SMU7_I2C_DDCVGADATA 0x4c
#define SMU7_I2C_DDCVGACLK 0x4d
#define SMU7_UNUSED_GPIO_PIN 0x7F
uint8_t smu7_get_sleep_divider_id_from_clock(uint32_t clock,
uint32_t clock_insr);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,62 @@
/*
* Copyright 2015 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.
*
*/
#ifndef _SMU7_POWERTUNE_H
#define _SMU7_POWERTUNE_H
#define DIDT_SQ_CTRL0__UNUSED_0_MASK 0xfffc0000
#define DIDT_SQ_CTRL0__UNUSED_0__SHIFT 0x12
#define DIDT_TD_CTRL0__UNUSED_0_MASK 0xfffc0000
#define DIDT_TD_CTRL0__UNUSED_0__SHIFT 0x12
#define DIDT_TCP_CTRL0__UNUSED_0_MASK 0xfffc0000
#define DIDT_TCP_CTRL0__UNUSED_0__SHIFT 0x12
#define DIDT_SQ_TUNING_CTRL__UNUSED_0_MASK 0xc0000000
#define DIDT_SQ_TUNING_CTRL__UNUSED_0__SHIFT 0x0000001e
#define DIDT_TD_TUNING_CTRL__UNUSED_0_MASK 0xc0000000
#define DIDT_TD_TUNING_CTRL__UNUSED_0__SHIFT 0x0000001e
#define DIDT_TCP_TUNING_CTRL__UNUSED_0_MASK 0xc0000000
#define DIDT_TCP_TUNING_CTRL__UNUSED_0__SHIFT 0x0000001e
/* PowerContainment Features */
#define POWERCONTAINMENT_FEATURE_DTE 0x00000001
#define POWERCONTAINMENT_FEATURE_TDCLimit 0x00000002
#define POWERCONTAINMENT_FEATURE_PkgPwrLimit 0x00000004
#define ixGC_CAC_CNTL 0x0000
#define ixDIDT_SQ_STALL_CTRL 0x0004
#define ixDIDT_SQ_TUNING_CTRL 0x0005
#define ixDIDT_TD_STALL_CTRL 0x0044
#define ixDIDT_TD_TUNING_CTRL 0x0045
#define ixDIDT_TCP_STALL_CTRL 0x0064
#define ixDIDT_TCP_TUNING_CTRL 0x0065
int smu7_enable_smc_cac(struct pp_hwmgr *hwmgr);
int smu7_disable_smc_cac(struct pp_hwmgr *hwmgr);
int smu7_enable_power_containment(struct pp_hwmgr *hwmgr);
int smu7_disable_power_containment(struct pp_hwmgr *hwmgr);
int smu7_set_power_limit(struct pp_hwmgr *hwmgr, uint32_t n);
int smu7_power_control_set_level(struct pp_hwmgr *hwmgr);
int smu7_enable_didt_config(struct pp_hwmgr *hwmgr);
int smu7_disable_didt_config(struct pp_hwmgr *hwmgr);
#endif /* DGPU_POWERTUNE_H */

View File

@@ -0,0 +1,471 @@
/*
* 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 <asm/div64.h>
#include "smu7_thermal.h"
#include "smu7_hwmgr.h"
#include "smu7_common.h"
int smu7_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr,
struct phm_fan_speed_info *fan_speed_info)
{
if (hwmgr->thermal_controller.fanInfo.bNoFan)
return -ENODEV;
fan_speed_info->supports_percent_read = true;
fan_speed_info->supports_percent_write = true;
fan_speed_info->min_percent = 0;
fan_speed_info->max_percent = 100;
if (PP_CAP(PHM_PlatformCaps_FanSpeedInTableIsRPM) &&
hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution) {
fan_speed_info->supports_rpm_read = true;
fan_speed_info->supports_rpm_write = true;
fan_speed_info->min_rpm = hwmgr->thermal_controller.fanInfo.ulMinRPM;
fan_speed_info->max_rpm = hwmgr->thermal_controller.fanInfo.ulMaxRPM;
} else {
fan_speed_info->min_rpm = 0;
fan_speed_info->max_rpm = 0;
}
return 0;
}
int smu7_fan_ctrl_get_fan_speed_percent(struct pp_hwmgr *hwmgr,
uint32_t *speed)
{
uint32_t duty100;
uint32_t duty;
uint64_t tmp64;
if (hwmgr->thermal_controller.fanInfo.bNoFan)
return -ENODEV;
duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
CG_FDO_CTRL1, FMAX_DUTY100);
duty = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
CG_THERMAL_STATUS, FDO_PWM_DUTY);
if (duty100 == 0)
return -EINVAL;
tmp64 = (uint64_t)duty * 100;
do_div(tmp64, duty100);
*speed = (uint32_t)tmp64;
if (*speed > 100)
*speed = 100;
return 0;
}
int smu7_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t *speed)
{
uint32_t tach_period;
uint32_t crystal_clock_freq;
if (hwmgr->thermal_controller.fanInfo.bNoFan ||
!hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution)
return -ENODEV;
tach_period = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
CG_TACH_STATUS, TACH_PERIOD);
if (tach_period == 0)
return -EINVAL;
crystal_clock_freq = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev);
*speed = 60 * crystal_clock_freq * 10000 / tach_period;
return 0;
}
/**
* Set Fan Speed Control to static mode, so that the user can decide what speed to use.
* @param hwmgr the address of the powerplay hardware manager.
* mode the fan control mode, 0 default, 1 by percent, 5, by RPM
* @exception Should always succeed.
*/
int smu7_fan_ctrl_set_static_mode(struct pp_hwmgr *hwmgr, uint32_t mode)
{
if (hwmgr->fan_ctrl_is_in_default_mode) {
hwmgr->fan_ctrl_default_mode =
PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
CG_FDO_CTRL2, FDO_PWM_MODE);
hwmgr->tmin =
PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
CG_FDO_CTRL2, TMIN);
hwmgr->fan_ctrl_is_in_default_mode = false;
}
PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
CG_FDO_CTRL2, TMIN, 0);
PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
CG_FDO_CTRL2, FDO_PWM_MODE, mode);
return 0;
}
/**
* Reset Fan Speed Control to default mode.
* @param hwmgr the address of the powerplay hardware manager.
* @exception Should always succeed.
*/
int smu7_fan_ctrl_set_default_mode(struct pp_hwmgr *hwmgr)
{
if (!hwmgr->fan_ctrl_is_in_default_mode) {
PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
CG_FDO_CTRL2, FDO_PWM_MODE, hwmgr->fan_ctrl_default_mode);
PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
CG_FDO_CTRL2, TMIN, hwmgr->tmin);
hwmgr->fan_ctrl_is_in_default_mode = true;
}
return 0;
}
int smu7_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr)
{
int result;
if (PP_CAP(PHM_PlatformCaps_ODFuzzyFanControlSupport)) {
result = smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_StartFanControl,
FAN_CONTROL_FUZZY, NULL);
if (PP_CAP(PHM_PlatformCaps_FanSpeedInTableIsRPM))
hwmgr->hwmgr_func->set_max_fan_rpm_output(hwmgr,
hwmgr->thermal_controller.
advanceFanControlParameters.usMaxFanRPM);
else
hwmgr->hwmgr_func->set_max_fan_pwm_output(hwmgr,
hwmgr->thermal_controller.
advanceFanControlParameters.usMaxFanPWM);
} else {
result = smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_StartFanControl,
FAN_CONTROL_TABLE, NULL);
}
if (!result && hwmgr->thermal_controller.
advanceFanControlParameters.ucTargetTemperature)
result = smum_send_msg_to_smc_with_parameter(hwmgr,
PPSMC_MSG_SetFanTemperatureTarget,
hwmgr->thermal_controller.
advanceFanControlParameters.ucTargetTemperature,
NULL);
hwmgr->fan_ctrl_enabled = true;
return result;
}
int smu7_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr)
{
hwmgr->fan_ctrl_enabled = false;
return smum_send_msg_to_smc(hwmgr, PPSMC_StopFanControl, NULL);
}
/**
* Set Fan Speed in percent.
* @param hwmgr the address of the powerplay hardware manager.
* @param speed is the percentage value (0% - 100%) to be set.
* @exception Fails is the 100% setting appears to be 0.
*/
int smu7_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr,
uint32_t speed)
{
uint32_t duty100;
uint32_t duty;
uint64_t tmp64;
if (hwmgr->thermal_controller.fanInfo.bNoFan)
return 0;
if (speed > 100)
speed = 100;
if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl))
smu7_fan_ctrl_stop_smc_fan_control(hwmgr);
duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
CG_FDO_CTRL1, FMAX_DUTY100);
if (duty100 == 0)
return -EINVAL;
tmp64 = (uint64_t)speed * duty100;
do_div(tmp64, 100);
duty = (uint32_t)tmp64;
PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
CG_FDO_CTRL0, FDO_STATIC_DUTY, duty);
return smu7_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC);
}
/**
* Reset Fan Speed to default.
* @param hwmgr the address of the powerplay hardware manager.
* @exception Always succeeds.
*/
int smu7_fan_ctrl_reset_fan_speed_to_default(struct pp_hwmgr *hwmgr)
{
int result;
if (hwmgr->thermal_controller.fanInfo.bNoFan)
return 0;
if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) {
result = smu7_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC);
if (!result)
result = smu7_fan_ctrl_start_smc_fan_control(hwmgr);
} else
result = smu7_fan_ctrl_set_default_mode(hwmgr);
return result;
}
/**
* Set Fan Speed in RPM.
* @param hwmgr the address of the powerplay hardware manager.
* @param speed is the percentage value (min - max) to be set.
* @exception Fails is the speed not lie between min and max.
*/
int smu7_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed)
{
uint32_t tach_period;
uint32_t crystal_clock_freq;
if (hwmgr->thermal_controller.fanInfo.bNoFan ||
(hwmgr->thermal_controller.fanInfo.
ucTachometerPulsesPerRevolution == 0) ||
speed == 0 ||
(speed < hwmgr->thermal_controller.fanInfo.ulMinRPM) ||
(speed > hwmgr->thermal_controller.fanInfo.ulMaxRPM))
return 0;
if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl))
smu7_fan_ctrl_stop_smc_fan_control(hwmgr);
crystal_clock_freq = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev);
tach_period = 60 * crystal_clock_freq * 10000 / (8 * speed);
PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
CG_TACH_CTRL, TARGET_PERIOD, tach_period);
return smu7_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC_RPM);
}
/**
* Reads the remote temperature from the SIslands thermal controller.
*
* @param hwmgr The address of the hardware manager.
*/
int smu7_thermal_get_temperature(struct pp_hwmgr *hwmgr)
{
int temp;
temp = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
CG_MULT_THERMAL_STATUS, CTF_TEMP);
/* Bit 9 means the reading is lower than the lowest usable value. */
if (temp & 0x200)
temp = SMU7_THERMAL_MAXIMUM_TEMP_READING;
else
temp = temp & 0x1ff;
temp *= PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
return temp;
}
/**
* Set the requested temperature range for high and low alert signals
*
* @param hwmgr The address of the hardware manager.
* @param range Temperature range to be programmed for high and low alert signals
* @exception PP_Result_BadInput if the input data is not valid.
*/
static int smu7_thermal_set_temperature_range(struct pp_hwmgr *hwmgr,
int low_temp, int high_temp)
{
int low = SMU7_THERMAL_MINIMUM_ALERT_TEMP *
PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
int high = SMU7_THERMAL_MAXIMUM_ALERT_TEMP *
PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
if (low < low_temp)
low = low_temp;
if (high > high_temp)
high = high_temp;
if (low > high)
return -EINVAL;
PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
CG_THERMAL_INT, DIG_THERM_INTH,
(high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES));
PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
CG_THERMAL_INT, DIG_THERM_INTL,
(low / PP_TEMPERATURE_UNITS_PER_CENTIGRADES));
PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
CG_THERMAL_CTRL, DIG_THERM_DPM,
(high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES));
return 0;
}
/**
* Programs thermal controller one-time setting registers
*
* @param hwmgr The address of the hardware manager.
*/
static int smu7_thermal_initialize(struct pp_hwmgr *hwmgr)
{
if (hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution)
PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
CG_TACH_CTRL, EDGE_PER_REV,
hwmgr->thermal_controller.fanInfo.
ucTachometerPulsesPerRevolution - 1);
PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
CG_FDO_CTRL2, TACH_PWM_RESP_RATE, 0x28);
return 0;
}
/**
* Enable thermal alerts on the RV770 thermal controller.
*
* @param hwmgr The address of the hardware manager.
*/
static void smu7_thermal_enable_alert(struct pp_hwmgr *hwmgr)
{
uint32_t alert;
alert = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
CG_THERMAL_INT, THERM_INT_MASK);
alert &= ~(SMU7_THERMAL_HIGH_ALERT_MASK | SMU7_THERMAL_LOW_ALERT_MASK);
PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
CG_THERMAL_INT, THERM_INT_MASK, alert);
/* send message to SMU to enable internal thermal interrupts */
smum_send_msg_to_smc(hwmgr, PPSMC_MSG_Thermal_Cntl_Enable, NULL);
}
/**
* Disable thermal alerts on the RV770 thermal controller.
* @param hwmgr The address of the hardware manager.
*/
int smu7_thermal_disable_alert(struct pp_hwmgr *hwmgr)
{
uint32_t alert;
alert = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
CG_THERMAL_INT, THERM_INT_MASK);
alert |= (SMU7_THERMAL_HIGH_ALERT_MASK | SMU7_THERMAL_LOW_ALERT_MASK);
PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
CG_THERMAL_INT, THERM_INT_MASK, alert);
/* send message to SMU to disable internal thermal interrupts */
return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_Thermal_Cntl_Disable, NULL);
}
/**
* Uninitialize the thermal controller.
* Currently just disables alerts.
* @param hwmgr The address of the hardware manager.
*/
int smu7_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr)
{
int result = smu7_thermal_disable_alert(hwmgr);
if (!hwmgr->thermal_controller.fanInfo.bNoFan)
smu7_fan_ctrl_set_default_mode(hwmgr);
return result;
}
/**
* Start the fan control on the SMC.
* @param hwmgr the address of the powerplay hardware manager.
* @param pInput the pointer to input data
* @param pOutput the pointer to output data
* @param pStorage the pointer to temporary storage
* @param Result the last failure code
* @return result from set temperature range routine
*/
static int smu7_thermal_start_smc_fan_control(struct pp_hwmgr *hwmgr)
{
/* If the fantable setup has failed we could have disabled
* PHM_PlatformCaps_MicrocodeFanControl even after
* this function was included in the table.
* Make sure that we still think controlling the fan is OK.
*/
if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) {
smu7_fan_ctrl_start_smc_fan_control(hwmgr);
smu7_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC);
}
return 0;
}
int smu7_start_thermal_controller(struct pp_hwmgr *hwmgr,
struct PP_TemperatureRange *range)
{
int ret = 0;
if (range == NULL)
return -EINVAL;
smu7_thermal_initialize(hwmgr);
ret = smu7_thermal_set_temperature_range(hwmgr, range->min, range->max);
if (ret)
return -EINVAL;
smu7_thermal_enable_alert(hwmgr);
ret = smum_thermal_avfs_enable(hwmgr);
if (ret)
return -EINVAL;
/* We should restrict performance levels to low before we halt the SMC.
* On the other hand we are still in boot state when we do this
* so it would be pointless.
* If this assumption changes we have to revisit this table.
*/
smum_thermal_setup_fan_table(hwmgr);
smu7_thermal_start_smc_fan_control(hwmgr);
return 0;
}
int smu7_thermal_ctrl_uninitialize_thermal_controller(struct pp_hwmgr *hwmgr)
{
if (!hwmgr->thermal_controller.fanInfo.bNoFan)
smu7_fan_ctrl_set_default_mode(hwmgr);
return 0;
}

View File

@@ -0,0 +1,58 @@
/*
* 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.
*
*/
#ifndef _SMU7_THERMAL_H_
#define _SMU7_THERMAL_H_
#include "hwmgr.h"
#define SMU7_THERMAL_HIGH_ALERT_MASK 0x1
#define SMU7_THERMAL_LOW_ALERT_MASK 0x2
#define SMU7_THERMAL_MINIMUM_TEMP_READING -256
#define SMU7_THERMAL_MAXIMUM_TEMP_READING 255
#define SMU7_THERMAL_MINIMUM_ALERT_TEMP 0
#define SMU7_THERMAL_MAXIMUM_ALERT_TEMP 255
#define FDO_PWM_MODE_STATIC 1
#define FDO_PWM_MODE_STATIC_RPM 5
extern int smu7_thermal_get_temperature(struct pp_hwmgr *hwmgr);
extern int smu7_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr);
extern int smu7_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr, struct phm_fan_speed_info *fan_speed_info);
extern int smu7_fan_ctrl_get_fan_speed_percent(struct pp_hwmgr *hwmgr, uint32_t *speed);
extern int smu7_fan_ctrl_set_default_mode(struct pp_hwmgr *hwmgr);
extern int smu7_fan_ctrl_set_static_mode(struct pp_hwmgr *hwmgr, uint32_t mode);
extern int smu7_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr, uint32_t speed);
extern int smu7_fan_ctrl_reset_fan_speed_to_default(struct pp_hwmgr *hwmgr);
extern int smu7_thermal_ctrl_uninitialize_thermal_controller(struct pp_hwmgr *hwmgr);
extern int smu7_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed);
extern int smu7_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t *speed);
extern int smu7_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr);
extern int smu7_thermal_disable_alert(struct pp_hwmgr *hwmgr);
extern int smu7_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr);
extern int smu7_start_thermal_controller(struct pp_hwmgr *hwmgr,
struct PP_TemperatureRange *temperature_range);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,311 @@
/*
* Copyright 2015 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.
*
*/
#ifndef _SMU8_HWMGR_H_
#define _SMU8_HWMGR_H_
#include "cgs_common.h"
#include "ppatomctrl.h"
#define SMU8_NUM_NBPSTATES 4
#define SMU8_NUM_NBPMEMORYCLOCK 2
#define MAX_DISPLAY_CLOCK_LEVEL 8
#define SMU8_MAX_HARDWARE_POWERLEVELS 8
#define SMU8_VOTINGRIGHTSCLIENTS_DFLT0 0x3FFFC102
#define SMU8_MIN_DEEP_SLEEP_SCLK 800
/* Carrizo device IDs */
#define DEVICE_ID_CZ_9870 0x9870
#define DEVICE_ID_CZ_9874 0x9874
#define DEVICE_ID_CZ_9875 0x9875
#define DEVICE_ID_CZ_9876 0x9876
#define DEVICE_ID_CZ_9877 0x9877
struct smu8_dpm_entry {
uint32_t soft_min_clk;
uint32_t hard_min_clk;
uint32_t soft_max_clk;
uint32_t hard_max_clk;
};
struct smu8_sys_info {
uint32_t bootup_uma_clock;
uint32_t bootup_engine_clock;
uint32_t dentist_vco_freq;
uint32_t nb_dpm_enable;
uint32_t nbp_memory_clock[SMU8_NUM_NBPMEMORYCLOCK];
uint32_t nbp_n_clock[SMU8_NUM_NBPSTATES];
uint16_t nbp_voltage_index[SMU8_NUM_NBPSTATES];
uint32_t display_clock[MAX_DISPLAY_CLOCK_LEVEL];
uint16_t bootup_nb_voltage_index;
uint8_t htc_tmp_lmt;
uint8_t htc_hyst_lmt;
uint32_t system_config;
uint32_t uma_channel_number;
};
#define MAX_DISPLAYPHY_IDS 0x8
#define DISPLAYPHY_LANEMASK 0xF
#define UNKNOWN_TRANSMITTER_PHY_ID (-1)
#define DISPLAYPHY_PHYID_SHIFT 24
#define DISPLAYPHY_LANESELECT_SHIFT 16
#define DISPLAYPHY_RX_SELECT 0x1
#define DISPLAYPHY_TX_SELECT 0x2
#define DISPLAYPHY_CORE_SELECT 0x4
#define DDI_POWERGATING_ARG(phyID, lanemask, rx, tx, core) \
(((uint32_t)(phyID))<<DISPLAYPHY_PHYID_SHIFT | \
((uint32_t)(lanemask))<<DISPLAYPHY_LANESELECT_SHIFT | \
((rx) ? DISPLAYPHY_RX_SELECT : 0) | \
((tx) ? DISPLAYPHY_TX_SELECT : 0) | \
((core) ? DISPLAYPHY_CORE_SELECT : 0))
struct smu8_display_phy_info_entry {
uint8_t phy_present;
uint8_t active_lane_mapping;
uint8_t display_config_type;
uint8_t active_number_of_lanes;
};
#define SMU8_MAX_DISPLAYPHY_IDS 10
struct smu8_display_phy_info {
bool display_phy_access_initialized;
struct smu8_display_phy_info_entry entries[SMU8_MAX_DISPLAYPHY_IDS];
};
struct smu8_power_level {
uint32_t engineClock;
uint8_t vddcIndex;
uint8_t dsDividerIndex;
uint8_t ssDividerIndex;
uint8_t allowGnbSlow;
uint8_t forceNBPstate;
uint8_t display_wm;
uint8_t vce_wm;
uint8_t numSIMDToPowerDown;
uint8_t hysteresis_up;
uint8_t rsv[3];
};
struct smu8_uvd_clocks {
uint32_t vclk;
uint32_t dclk;
uint32_t vclk_low_divider;
uint32_t vclk_high_divider;
uint32_t dclk_low_divider;
uint32_t dclk_high_divider;
};
enum smu8_pstate_previous_action {
DO_NOTHING = 1,
FORCE_HIGH,
CANCEL_FORCE_HIGH
};
struct pp_disable_nb_ps_flags {
union {
struct {
uint32_t entry : 1;
uint32_t display : 1;
uint32_t driver: 1;
uint32_t vce : 1;
uint32_t uvd : 1;
uint32_t acp : 1;
uint32_t reserved: 26;
} bits;
uint32_t u32All;
};
};
struct smu8_power_state {
unsigned int magic;
uint32_t level;
struct smu8_uvd_clocks uvd_clocks;
uint32_t evclk;
uint32_t ecclk;
uint32_t samclk;
uint32_t acpclk;
bool need_dfs_bypass;
uint32_t nbps_flags;
uint32_t bapm_flags;
uint8_t dpm_0_pg_nb_ps_low;
uint8_t dpm_0_pg_nb_ps_high;
uint8_t dpm_x_nb_ps_low;
uint8_t dpm_x_nb_ps_high;
enum smu8_pstate_previous_action action;
struct smu8_power_level levels[SMU8_MAX_HARDWARE_POWERLEVELS];
struct pp_disable_nb_ps_flags disable_nb_ps_flag;
};
#define DPMFlags_SCLK_Enabled 0x00000001
#define DPMFlags_UVD_Enabled 0x00000002
#define DPMFlags_VCE_Enabled 0x00000004
#define DPMFlags_ACP_Enabled 0x00000008
#define DPMFlags_ForceHighestValid 0x40000000
#define DPMFlags_Debug 0x80000000
#define SMU_EnabledFeatureScoreboard_AcpDpmOn 0x00000001 /* bit 0 */
#define SMU_EnabledFeatureScoreboard_UvdDpmOn 0x00800000 /* bit 23 */
#define SMU_EnabledFeatureScoreboard_VceDpmOn 0x01000000 /* bit 24 */
struct cc6_settings {
bool cc6_setting_changed;
bool nb_pstate_switch_disable;/* controls NB PState switch */
bool cpu_cc6_disable; /* controls CPU CState switch ( on or off) */
bool cpu_pstate_disable;
uint32_t cpu_pstate_separation_time;
};
struct smu8_hwmgr {
uint32_t dpm_interval;
uint32_t voltage_drop_threshold;
uint32_t voting_rights_clients;
uint32_t disable_driver_thermal_policy;
uint32_t static_screen_threshold;
uint32_t gfx_power_gating_threshold;
uint32_t activity_hysteresis;
uint32_t bootup_sclk_divider;
uint32_t gfx_ramp_step;
uint32_t gfx_ramp_delay; /* in micro-seconds */
uint32_t thermal_auto_throttling_treshold;
struct smu8_sys_info sys_info;
struct smu8_power_level boot_power_level;
struct smu8_power_state *smu8_current_ps;
struct smu8_power_state *smu8_requested_ps;
uint32_t mgcg_cgtt_local0;
uint32_t mgcg_cgtt_local1;
uint32_t tdr_clock; /* in 10khz unit */
uint32_t ddi_power_gating_disabled;
uint32_t disable_gfx_power_gating_in_uvd;
uint32_t disable_nb_ps3_in_battery;
uint32_t lock_nb_ps_in_uvd_play_back;
struct smu8_display_phy_info display_phy_info;
uint32_t vce_slow_sclk_threshold; /* default 200mhz */
uint32_t dce_slow_sclk_threshold; /* default 300mhz */
uint32_t min_sclk_did; /* minimum sclk divider */
bool disp_clk_bypass;
bool disp_clk_bypass_pending;
uint32_t bapm_enabled;
uint32_t clock_slow_down_freq;
uint32_t skip_clock_slow_down;
uint32_t enable_nb_ps_policy;
uint32_t voltage_drop_in_dce_power_gating;
uint32_t uvd_dpm_interval;
uint32_t override_dynamic_mgpg;
uint32_t lclk_deep_enabled;
uint32_t uvd_performance;
bool video_start;
bool battery_state;
uint32_t lowest_valid;
uint32_t highest_valid;
uint32_t high_voltage_threshold;
uint32_t is_nb_dpm_enabled;
struct cc6_settings cc6_settings;
uint32_t is_voltage_island_enabled;
bool pgacpinit;
uint8_t disp_config;
/* PowerTune */
uint32_t power_containment_features;
bool cac_enabled;
bool disable_uvd_power_tune_feature;
bool enable_ba_pm_feature;
bool enable_tdc_limit_feature;
uint32_t sram_end;
uint32_t dpm_table_start;
uint32_t soft_regs_start;
uint8_t uvd_level_count;
uint8_t vce_level_count;
uint8_t acp_level_count;
uint8_t samu_level_count;
uint32_t fps_high_threshold;
uint32_t fps_low_threshold;
uint32_t dpm_flags;
struct smu8_dpm_entry sclk_dpm;
struct smu8_dpm_entry uvd_dpm;
struct smu8_dpm_entry vce_dpm;
struct smu8_dpm_entry acp_dpm;
uint8_t uvd_boot_level;
uint8_t vce_boot_level;
uint8_t acp_boot_level;
uint8_t samu_boot_level;
uint8_t uvd_interval;
uint8_t vce_interval;
uint8_t acp_interval;
uint8_t samu_interval;
uint8_t graphics_interval;
uint8_t graphics_therm_throttle_enable;
uint8_t graphics_voltage_change_enable;
uint8_t graphics_clk_slow_enable;
uint8_t graphics_clk_slow_divider;
uint32_t display_cac;
uint32_t low_sclk_interrupt_threshold;
uint32_t dram_log_addr_h;
uint32_t dram_log_addr_l;
uint32_t dram_log_phy_addr_h;
uint32_t dram_log_phy_addr_l;
uint32_t dram_log_buff_size;
bool uvd_power_gated;
bool vce_power_gated;
bool samu_power_gated;
bool acp_power_gated;
bool acp_power_up_no_dsp;
uint32_t active_process_mask;
uint32_t max_sclk_level;
uint32_t num_of_clk_entries;
};
#endif /* _SMU8_HWMGR_H_ */

View File

@@ -0,0 +1,66 @@
/*
* Copyright 2018 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 "soc15.h"
#include "soc15_hw_ip.h"
#include "vega10_ip_offset.h"
#include "soc15_common.h"
#include "vega10_inc.h"
#include "smu9_baco.h"
int smu9_baco_get_capability(struct pp_hwmgr *hwmgr, bool *cap)
{
struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev);
uint32_t reg, data;
*cap = false;
if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_BACO))
return 0;
WREG32(0x12074, 0xFFF0003B);
data = RREG32(0x12075);
if (data == 0x1) {
reg = RREG32_SOC15(NBIF, 0, mmRCC_BIF_STRAP0);
if (reg & RCC_BIF_STRAP0__STRAP_PX_CAPABLE_MASK)
*cap = true;
}
return 0;
}
int smu9_baco_get_state(struct pp_hwmgr *hwmgr, enum BACO_STATE *state)
{
struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev);
uint32_t reg;
reg = RREG32_SOC15(NBIF, 0, mmBACO_CNTL);
if (reg & BACO_CNTL__BACO_MODE_MASK)
/* gfx has already entered BACO state */
*state = BACO_STATE_IN;
else
*state = BACO_STATE_OUT;
return 0;
}

View File

@@ -0,0 +1,31 @@
/*
* Copyright 2018 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.
*
*/
#ifndef __SMU9_BACO_H__
#define __SMU9_BACO_H__
#include "hwmgr.h"
#include "common_baco.h"
extern int smu9_baco_get_capability(struct pp_hwmgr *hwmgr, bool *cap);
extern int smu9_baco_get_state(struct pp_hwmgr *hwmgr, enum BACO_STATE *state);
#endif

View File

@@ -0,0 +1,767 @@
/*
* Copyright 2018 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/pci.h>
#include <linux/reboot.h>
#include "hwmgr.h"
#include "pp_debug.h"
#include "ppatomctrl.h"
#include "ppsmc.h"
#include "atom.h"
#include "ivsrcid/thm/irqsrcs_thm_9_0.h"
#include "ivsrcid/smuio/irqsrcs_smuio_9_0.h"
#include "ivsrcid/ivsrcid_vislands30.h"
uint8_t convert_to_vid(uint16_t vddc)
{
return (uint8_t) ((6200 - (vddc * VOLTAGE_SCALE)) / 25);
}
uint16_t convert_to_vddc(uint8_t vid)
{
return (uint16_t) ((6200 - (vid * 25)) / VOLTAGE_SCALE);
}
int phm_copy_clock_limits_array(
struct pp_hwmgr *hwmgr,
uint32_t **pptable_info_array,
const uint32_t *pptable_array,
uint32_t power_saving_clock_count)
{
uint32_t array_size, i;
uint32_t *table;
array_size = sizeof(uint32_t) * power_saving_clock_count;
table = kzalloc(array_size, GFP_KERNEL);
if (NULL == table)
return -ENOMEM;
for (i = 0; i < power_saving_clock_count; i++)
table[i] = le32_to_cpu(pptable_array[i]);
*pptable_info_array = table;
return 0;
}
int phm_copy_overdrive_settings_limits_array(
struct pp_hwmgr *hwmgr,
uint32_t **pptable_info_array,
const uint32_t *pptable_array,
uint32_t od_setting_count)
{
uint32_t array_size, i;
uint32_t *table;
array_size = sizeof(uint32_t) * od_setting_count;
table = kzalloc(array_size, GFP_KERNEL);
if (NULL == table)
return -ENOMEM;
for (i = 0; i < od_setting_count; i++)
table[i] = le32_to_cpu(pptable_array[i]);
*pptable_info_array = table;
return 0;
}
uint32_t phm_set_field_to_u32(u32 offset, u32 original_data, u32 field, u32 size)
{
u32 mask = 0;
u32 shift = 0;
shift = (offset % 4) << 3;
if (size == sizeof(uint8_t))
mask = 0xFF << shift;
else if (size == sizeof(uint16_t))
mask = 0xFFFF << shift;
original_data &= ~mask;
original_data |= (field << shift);
return original_data;
}
/**
* Returns once the part of the register indicated by the mask has
* reached the given value.
*/
int phm_wait_on_register(struct pp_hwmgr *hwmgr, uint32_t index,
uint32_t value, uint32_t mask)
{
uint32_t i;
uint32_t cur_value;
if (hwmgr == NULL || hwmgr->device == NULL) {
pr_err("Invalid Hardware Manager!");
return -EINVAL;
}
for (i = 0; i < hwmgr->usec_timeout; i++) {
cur_value = cgs_read_register(hwmgr->device, index);
if ((cur_value & mask) == (value & mask))
break;
udelay(1);
}
/* timeout means wrong logic*/
if (i == hwmgr->usec_timeout)
return -1;
return 0;
}
/**
* Returns once the part of the register indicated by the mask has
* reached the given value.The indirect space is described by giving
* the memory-mapped index of the indirect index register.
*/
int phm_wait_on_indirect_register(struct pp_hwmgr *hwmgr,
uint32_t indirect_port,
uint32_t index,
uint32_t value,
uint32_t mask)
{
if (hwmgr == NULL || hwmgr->device == NULL) {
pr_err("Invalid Hardware Manager!");
return -EINVAL;
}
cgs_write_register(hwmgr->device, indirect_port, index);
return phm_wait_on_register(hwmgr, indirect_port + 1, mask, value);
}
int phm_wait_for_register_unequal(struct pp_hwmgr *hwmgr,
uint32_t index,
uint32_t value, uint32_t mask)
{
uint32_t i;
uint32_t cur_value;
if (hwmgr == NULL || hwmgr->device == NULL)
return -EINVAL;
for (i = 0; i < hwmgr->usec_timeout; i++) {
cur_value = cgs_read_register(hwmgr->device,
index);
if ((cur_value & mask) != (value & mask))
break;
udelay(1);
}
/* timeout means wrong logic */
if (i == hwmgr->usec_timeout)
return -ETIME;
return 0;
}
int phm_wait_for_indirect_register_unequal(struct pp_hwmgr *hwmgr,
uint32_t indirect_port,
uint32_t index,
uint32_t value,
uint32_t mask)
{
if (hwmgr == NULL || hwmgr->device == NULL)
return -EINVAL;
cgs_write_register(hwmgr->device, indirect_port, index);
return phm_wait_for_register_unequal(hwmgr, indirect_port + 1,
value, mask);
}
bool phm_cf_want_uvd_power_gating(struct pp_hwmgr *hwmgr)
{
return phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_UVDPowerGating);
}
bool phm_cf_want_vce_power_gating(struct pp_hwmgr *hwmgr)
{
return phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_VCEPowerGating);
}
int phm_trim_voltage_table(struct pp_atomctrl_voltage_table *vol_table)
{
uint32_t i, j;
uint16_t vvalue;
bool found = false;
struct pp_atomctrl_voltage_table *table;
PP_ASSERT_WITH_CODE((NULL != vol_table),
"Voltage Table empty.", return -EINVAL);
table = kzalloc(sizeof(struct pp_atomctrl_voltage_table),
GFP_KERNEL);
if (NULL == table)
return -EINVAL;
table->mask_low = vol_table->mask_low;
table->phase_delay = vol_table->phase_delay;
for (i = 0; i < vol_table->count; i++) {
vvalue = vol_table->entries[i].value;
found = false;
for (j = 0; j < table->count; j++) {
if (vvalue == table->entries[j].value) {
found = true;
break;
}
}
if (!found) {
table->entries[table->count].value = vvalue;
table->entries[table->count].smio_low =
vol_table->entries[i].smio_low;
table->count++;
}
}
memcpy(vol_table, table, sizeof(struct pp_atomctrl_voltage_table));
kfree(table);
table = NULL;
return 0;
}
int phm_get_svi2_mvdd_voltage_table(struct pp_atomctrl_voltage_table *vol_table,
phm_ppt_v1_clock_voltage_dependency_table *dep_table)
{
uint32_t i;
int result;
PP_ASSERT_WITH_CODE((0 != dep_table->count),
"Voltage Dependency Table empty.", return -EINVAL);
PP_ASSERT_WITH_CODE((NULL != vol_table),
"vol_table empty.", return -EINVAL);
vol_table->mask_low = 0;
vol_table->phase_delay = 0;
vol_table->count = dep_table->count;
for (i = 0; i < dep_table->count; i++) {
vol_table->entries[i].value = dep_table->entries[i].mvdd;
vol_table->entries[i].smio_low = 0;
}
result = phm_trim_voltage_table(vol_table);
PP_ASSERT_WITH_CODE((0 == result),
"Failed to trim MVDD table.", return result);
return 0;
}
int phm_get_svi2_vddci_voltage_table(struct pp_atomctrl_voltage_table *vol_table,
phm_ppt_v1_clock_voltage_dependency_table *dep_table)
{
uint32_t i;
int result;
PP_ASSERT_WITH_CODE((0 != dep_table->count),
"Voltage Dependency Table empty.", return -EINVAL);
PP_ASSERT_WITH_CODE((NULL != vol_table),
"vol_table empty.", return -EINVAL);
vol_table->mask_low = 0;
vol_table->phase_delay = 0;
vol_table->count = dep_table->count;
for (i = 0; i < dep_table->count; i++) {
vol_table->entries[i].value = dep_table->entries[i].vddci;
vol_table->entries[i].smio_low = 0;
}
result = phm_trim_voltage_table(vol_table);
PP_ASSERT_WITH_CODE((0 == result),
"Failed to trim VDDCI table.", return result);
return 0;
}
int phm_get_svi2_vdd_voltage_table(struct pp_atomctrl_voltage_table *vol_table,
phm_ppt_v1_voltage_lookup_table *lookup_table)
{
int i = 0;
PP_ASSERT_WITH_CODE((0 != lookup_table->count),
"Voltage Lookup Table empty.", return -EINVAL);
PP_ASSERT_WITH_CODE((NULL != vol_table),
"vol_table empty.", return -EINVAL);
vol_table->mask_low = 0;
vol_table->phase_delay = 0;
vol_table->count = lookup_table->count;
for (i = 0; i < vol_table->count; i++) {
vol_table->entries[i].value = lookup_table->entries[i].us_vdd;
vol_table->entries[i].smio_low = 0;
}
return 0;
}
void phm_trim_voltage_table_to_fit_state_table(uint32_t max_vol_steps,
struct pp_atomctrl_voltage_table *vol_table)
{
unsigned int i, diff;
if (vol_table->count <= max_vol_steps)
return;
diff = vol_table->count - max_vol_steps;
for (i = 0; i < max_vol_steps; i++)
vol_table->entries[i] = vol_table->entries[i + diff];
vol_table->count = max_vol_steps;
return;
}
int phm_reset_single_dpm_table(void *table,
uint32_t count, int max)
{
int i;
struct vi_dpm_table *dpm_table = (struct vi_dpm_table *)table;
dpm_table->count = count > max ? max : count;
for (i = 0; i < dpm_table->count; i++)
dpm_table->dpm_level[i].enabled = false;
return 0;
}
void phm_setup_pcie_table_entry(
void *table,
uint32_t index, uint32_t pcie_gen,
uint32_t pcie_lanes)
{
struct vi_dpm_table *dpm_table = (struct vi_dpm_table *)table;
dpm_table->dpm_level[index].value = pcie_gen;
dpm_table->dpm_level[index].param1 = pcie_lanes;
dpm_table->dpm_level[index].enabled = 1;
}
int32_t phm_get_dpm_level_enable_mask_value(void *table)
{
int32_t i;
int32_t mask = 0;
struct vi_dpm_table *dpm_table = (struct vi_dpm_table *)table;
for (i = dpm_table->count; i > 0; i--) {
mask = mask << 1;
if (dpm_table->dpm_level[i - 1].enabled)
mask |= 0x1;
else
mask &= 0xFFFFFFFE;
}
return mask;
}
uint8_t phm_get_voltage_index(
struct phm_ppt_v1_voltage_lookup_table *lookup_table, uint16_t voltage)
{
uint8_t count = (uint8_t) (lookup_table->count);
uint8_t i;
PP_ASSERT_WITH_CODE((NULL != lookup_table),
"Lookup Table empty.", return 0);
PP_ASSERT_WITH_CODE((0 != count),
"Lookup Table empty.", return 0);
for (i = 0; i < lookup_table->count; i++) {
/* find first voltage equal or bigger than requested */
if (lookup_table->entries[i].us_vdd >= voltage)
return i;
}
/* voltage is bigger than max voltage in the table */
return i - 1;
}
uint8_t phm_get_voltage_id(pp_atomctrl_voltage_table *voltage_table,
uint32_t voltage)
{
uint8_t count = (uint8_t) (voltage_table->count);
uint8_t i = 0;
PP_ASSERT_WITH_CODE((NULL != voltage_table),
"Voltage Table empty.", return 0;);
PP_ASSERT_WITH_CODE((0 != count),
"Voltage Table empty.", return 0;);
for (i = 0; i < count; i++) {
/* find first voltage bigger than requested */
if (voltage_table->entries[i].value >= voltage)
return i;
}
/* voltage is bigger than max voltage in the table */
return i - 1;
}
uint16_t phm_find_closest_vddci(struct pp_atomctrl_voltage_table *vddci_table, uint16_t vddci)
{
uint32_t i;
for (i = 0; i < vddci_table->count; i++) {
if (vddci_table->entries[i].value >= vddci)
return vddci_table->entries[i].value;
}
pr_debug("vddci is larger than max value in vddci_table\n");
return vddci_table->entries[i-1].value;
}
int phm_find_boot_level(void *table,
uint32_t value, uint32_t *boot_level)
{
int result = -EINVAL;
uint32_t i;
struct vi_dpm_table *dpm_table = (struct vi_dpm_table *)table;
for (i = 0; i < dpm_table->count; i++) {
if (value == dpm_table->dpm_level[i].value) {
*boot_level = i;
result = 0;
}
}
return result;
}
int phm_get_sclk_for_voltage_evv(struct pp_hwmgr *hwmgr,
phm_ppt_v1_voltage_lookup_table *lookup_table,
uint16_t virtual_voltage_id, int32_t *sclk)
{
uint8_t entry_id;
uint8_t voltage_id;
struct phm_ppt_v1_information *table_info =
(struct phm_ppt_v1_information *)(hwmgr->pptable);
PP_ASSERT_WITH_CODE(lookup_table->count != 0, "Lookup table is empty", return -EINVAL);
/* search for leakage voltage ID 0xff01 ~ 0xff08 and sckl */
for (entry_id = 0; entry_id < table_info->vdd_dep_on_sclk->count; entry_id++) {
voltage_id = table_info->vdd_dep_on_sclk->entries[entry_id].vddInd;
if (lookup_table->entries[voltage_id].us_vdd == virtual_voltage_id)
break;
}
if (entry_id >= table_info->vdd_dep_on_sclk->count) {
pr_debug("Can't find requested voltage id in vdd_dep_on_sclk table\n");
return -EINVAL;
}
*sclk = table_info->vdd_dep_on_sclk->entries[entry_id].clk;
return 0;
}
/**
* Initialize Dynamic State Adjustment Rule Settings
*
* @param hwmgr the address of the powerplay hardware manager.
*/
int phm_initializa_dynamic_state_adjustment_rule_settings(struct pp_hwmgr *hwmgr)
{
uint32_t table_size;
struct phm_clock_voltage_dependency_table *table_clk_vlt;
struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
/* initialize vddc_dep_on_dal_pwrl table */
table_size = sizeof(uint32_t) + 4 * sizeof(struct phm_clock_voltage_dependency_record);
table_clk_vlt = kzalloc(table_size, GFP_KERNEL);
if (NULL == table_clk_vlt) {
pr_err("Can not allocate space for vddc_dep_on_dal_pwrl! \n");
return -ENOMEM;
} else {
table_clk_vlt->count = 4;
table_clk_vlt->entries[0].clk = PP_DAL_POWERLEVEL_ULTRALOW;
table_clk_vlt->entries[0].v = 0;
table_clk_vlt->entries[1].clk = PP_DAL_POWERLEVEL_LOW;
table_clk_vlt->entries[1].v = 720;
table_clk_vlt->entries[2].clk = PP_DAL_POWERLEVEL_NOMINAL;
table_clk_vlt->entries[2].v = 810;
table_clk_vlt->entries[3].clk = PP_DAL_POWERLEVEL_PERFORMANCE;
table_clk_vlt->entries[3].v = 900;
if (pptable_info != NULL)
pptable_info->vddc_dep_on_dal_pwrl = table_clk_vlt;
hwmgr->dyn_state.vddc_dep_on_dal_pwrl = table_clk_vlt;
}
return 0;
}
uint32_t phm_get_lowest_enabled_level(struct pp_hwmgr *hwmgr, uint32_t mask)
{
uint32_t level = 0;
while (0 == (mask & (1 << level)))
level++;
return level;
}
void phm_apply_dal_min_voltage_request(struct pp_hwmgr *hwmgr)
{
struct phm_ppt_v1_information *table_info =
(struct phm_ppt_v1_information *)hwmgr->pptable;
struct phm_clock_voltage_dependency_table *table =
table_info->vddc_dep_on_dal_pwrl;
struct phm_ppt_v1_clock_voltage_dependency_table *vddc_table;
enum PP_DAL_POWERLEVEL dal_power_level = hwmgr->dal_power_level;
uint32_t req_vddc = 0, req_volt, i;
if (!table || table->count <= 0
|| dal_power_level < PP_DAL_POWERLEVEL_ULTRALOW
|| dal_power_level > PP_DAL_POWERLEVEL_PERFORMANCE)
return;
for (i = 0; i < table->count; i++) {
if (dal_power_level == table->entries[i].clk) {
req_vddc = table->entries[i].v;
break;
}
}
vddc_table = table_info->vdd_dep_on_sclk;
for (i = 0; i < vddc_table->count; i++) {
if (req_vddc <= vddc_table->entries[i].vddc) {
req_volt = (((uint32_t)vddc_table->entries[i].vddc) * VOLTAGE_SCALE);
smum_send_msg_to_smc_with_parameter(hwmgr,
PPSMC_MSG_VddC_Request,
req_volt,
NULL);
return;
}
}
pr_err("DAL requested level can not"
" found a available voltage in VDDC DPM Table \n");
}
int phm_get_voltage_evv_on_sclk(struct pp_hwmgr *hwmgr, uint8_t voltage_type,
uint32_t sclk, uint16_t id, uint16_t *voltage)
{
uint32_t vol;
int ret = 0;
if (hwmgr->chip_id < CHIP_TONGA) {
ret = atomctrl_get_voltage_evv(hwmgr, id, voltage);
} else if (hwmgr->chip_id < CHIP_POLARIS10) {
ret = atomctrl_get_voltage_evv_on_sclk(hwmgr, voltage_type, sclk, id, voltage);
if (*voltage >= 2000 || *voltage == 0)
*voltage = 1150;
} else {
ret = atomctrl_get_voltage_evv_on_sclk_ai(hwmgr, voltage_type, sclk, id, &vol);
*voltage = (uint16_t)(vol/100);
}
return ret;
}
int phm_irq_process(struct amdgpu_device *adev,
struct amdgpu_irq_src *source,
struct amdgpu_iv_entry *entry)
{
uint32_t client_id = entry->client_id;
uint32_t src_id = entry->src_id;
if (client_id == AMDGPU_IRQ_CLIENTID_LEGACY) {
if (src_id == VISLANDS30_IV_SRCID_CG_TSS_THERMAL_LOW_TO_HIGH) {
dev_emerg(adev->dev, "ERROR: GPU over temperature range(SW CTF) detected!\n");
/*
* SW CTF just occurred.
* Try to do a graceful shutdown to prevent further damage.
*/
dev_emerg(adev->dev, "ERROR: System is going to shutdown due to GPU SW CTF!\n");
orderly_poweroff(true);
} else if (src_id == VISLANDS30_IV_SRCID_CG_TSS_THERMAL_HIGH_TO_LOW)
dev_emerg(adev->dev, "ERROR: GPU under temperature range detected!\n");
else if (src_id == VISLANDS30_IV_SRCID_GPIO_19) {
dev_emerg(adev->dev, "ERROR: GPU HW Critical Temperature Fault(aka CTF) detected!\n");
/*
* HW CTF just occurred. Shutdown to prevent further damage.
*/
dev_emerg(adev->dev, "ERROR: System is going to shutdown due to GPU HW CTF!\n");
orderly_poweroff(true);
}
} else if (client_id == SOC15_IH_CLIENTID_THM) {
if (src_id == 0) {
dev_emerg(adev->dev, "ERROR: GPU over temperature range(SW CTF) detected!\n");
/*
* SW CTF just occurred.
* Try to do a graceful shutdown to prevent further damage.
*/
dev_emerg(adev->dev, "ERROR: System is going to shutdown due to GPU SW CTF!\n");
orderly_poweroff(true);
} else
dev_emerg(adev->dev, "ERROR: GPU under temperature range detected!\n");
} else if (client_id == SOC15_IH_CLIENTID_ROM_SMUIO) {
dev_emerg(adev->dev, "ERROR: GPU HW Critical Temperature Fault(aka CTF) detected!\n");
/*
* HW CTF just occurred. Shutdown to prevent further damage.
*/
dev_emerg(adev->dev, "ERROR: System is going to shutdown due to GPU HW CTF!\n");
orderly_poweroff(true);
}
return 0;
}
static const struct amdgpu_irq_src_funcs smu9_irq_funcs = {
.process = phm_irq_process,
};
int smu9_register_irq_handlers(struct pp_hwmgr *hwmgr)
{
struct amdgpu_irq_src *source =
kzalloc(sizeof(struct amdgpu_irq_src), GFP_KERNEL);
if (!source)
return -ENOMEM;
source->funcs = &smu9_irq_funcs;
amdgpu_irq_add_id((struct amdgpu_device *)(hwmgr->adev),
SOC15_IH_CLIENTID_THM,
THM_9_0__SRCID__THM_DIG_THERM_L2H,
source);
amdgpu_irq_add_id((struct amdgpu_device *)(hwmgr->adev),
SOC15_IH_CLIENTID_THM,
THM_9_0__SRCID__THM_DIG_THERM_H2L,
source);
/* Register CTF(GPIO_19) interrupt */
amdgpu_irq_add_id((struct amdgpu_device *)(hwmgr->adev),
SOC15_IH_CLIENTID_ROM_SMUIO,
SMUIO_9_0__SRCID__SMUIO_GPIO19,
source);
return 0;
}
void *smu_atom_get_data_table(void *dev, uint32_t table, uint16_t *size,
uint8_t *frev, uint8_t *crev)
{
struct amdgpu_device *adev = dev;
uint16_t data_start;
if (amdgpu_atom_parse_data_header(
adev->mode_info.atom_context, table, size,
frev, crev, &data_start))
return (uint8_t *)adev->mode_info.atom_context->bios +
data_start;
return NULL;
}
int smu_get_voltage_dependency_table_ppt_v1(
const struct phm_ppt_v1_clock_voltage_dependency_table *allowed_dep_table,
struct phm_ppt_v1_clock_voltage_dependency_table *dep_table)
{
uint8_t i = 0;
PP_ASSERT_WITH_CODE((0 != allowed_dep_table->count),
"Voltage Lookup Table empty",
return -EINVAL);
dep_table->count = allowed_dep_table->count;
for (i=0; i<dep_table->count; i++) {
dep_table->entries[i].clk = allowed_dep_table->entries[i].clk;
dep_table->entries[i].vddInd = allowed_dep_table->entries[i].vddInd;
dep_table->entries[i].vdd_offset = allowed_dep_table->entries[i].vdd_offset;
dep_table->entries[i].vddc = allowed_dep_table->entries[i].vddc;
dep_table->entries[i].vddgfx = allowed_dep_table->entries[i].vddgfx;
dep_table->entries[i].vddci = allowed_dep_table->entries[i].vddci;
dep_table->entries[i].mvdd = allowed_dep_table->entries[i].mvdd;
dep_table->entries[i].phases = allowed_dep_table->entries[i].phases;
dep_table->entries[i].cks_enable = allowed_dep_table->entries[i].cks_enable;
dep_table->entries[i].cks_voffset = allowed_dep_table->entries[i].cks_voffset;
}
return 0;
}
int smu_set_watermarks_for_clocks_ranges(void *wt_table,
struct dm_pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges)
{
uint32_t i;
struct watermarks *table = wt_table;
if (!table || !wm_with_clock_ranges)
return -EINVAL;
if (wm_with_clock_ranges->num_wm_dmif_sets > 4 || wm_with_clock_ranges->num_wm_mcif_sets > 4)
return -EINVAL;
for (i = 0; i < wm_with_clock_ranges->num_wm_dmif_sets; i++) {
table->WatermarkRow[1][i].MinClock =
cpu_to_le16((uint16_t)
(wm_with_clock_ranges->wm_dmif_clocks_ranges[i].wm_min_dcfclk_clk_in_khz /
1000));
table->WatermarkRow[1][i].MaxClock =
cpu_to_le16((uint16_t)
(wm_with_clock_ranges->wm_dmif_clocks_ranges[i].wm_max_dcfclk_clk_in_khz /
1000));
table->WatermarkRow[1][i].MinUclk =
cpu_to_le16((uint16_t)
(wm_with_clock_ranges->wm_dmif_clocks_ranges[i].wm_min_mem_clk_in_khz /
1000));
table->WatermarkRow[1][i].MaxUclk =
cpu_to_le16((uint16_t)
(wm_with_clock_ranges->wm_dmif_clocks_ranges[i].wm_max_mem_clk_in_khz /
1000));
table->WatermarkRow[1][i].WmSetting = (uint8_t)
wm_with_clock_ranges->wm_dmif_clocks_ranges[i].wm_set_id;
}
for (i = 0; i < wm_with_clock_ranges->num_wm_mcif_sets; i++) {
table->WatermarkRow[0][i].MinClock =
cpu_to_le16((uint16_t)
(wm_with_clock_ranges->wm_mcif_clocks_ranges[i].wm_min_socclk_clk_in_khz /
1000));
table->WatermarkRow[0][i].MaxClock =
cpu_to_le16((uint16_t)
(wm_with_clock_ranges->wm_mcif_clocks_ranges[i].wm_max_socclk_clk_in_khz /
1000));
table->WatermarkRow[0][i].MinUclk =
cpu_to_le16((uint16_t)
(wm_with_clock_ranges->wm_mcif_clocks_ranges[i].wm_min_mem_clk_in_khz /
1000));
table->WatermarkRow[0][i].MaxUclk =
cpu_to_le16((uint16_t)
(wm_with_clock_ranges->wm_mcif_clocks_ranges[i].wm_max_mem_clk_in_khz /
1000));
table->WatermarkRow[0][i].WmSetting = (uint8_t)
wm_with_clock_ranges->wm_mcif_clocks_ranges[i].wm_set_id;
}
return 0;
}

View File

@@ -0,0 +1,228 @@
/*
* Copyright 2018 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.
*
*/
#ifndef _SMU_HELPER_H_
#define _SMU_HELPER_H_
struct pp_atomctrl_voltage_table;
struct pp_hwmgr;
struct phm_ppt_v1_voltage_lookup_table;
struct Watermarks_t;
struct pp_wm_sets_with_clock_ranges_soc15;
uint8_t convert_to_vid(uint16_t vddc);
uint16_t convert_to_vddc(uint8_t vid);
struct watermark_row_generic_t {
uint16_t MinClock;
uint16_t MaxClock;
uint16_t MinUclk;
uint16_t MaxUclk;
uint8_t WmSetting;
uint8_t Padding[3];
};
struct watermarks {
struct watermark_row_generic_t WatermarkRow[2][4];
uint32_t padding[7];
};
int phm_copy_clock_limits_array(
struct pp_hwmgr *hwmgr,
uint32_t **pptable_info_array,
const uint32_t *pptable_array,
uint32_t power_saving_clock_count);
int phm_copy_overdrive_settings_limits_array(
struct pp_hwmgr *hwmgr,
uint32_t **pptable_info_array,
const uint32_t *pptable_array,
uint32_t od_setting_count);
extern int phm_wait_for_register_unequal(struct pp_hwmgr *hwmgr,
uint32_t index,
uint32_t value, uint32_t mask);
extern int phm_wait_for_indirect_register_unequal(
struct pp_hwmgr *hwmgr,
uint32_t indirect_port, uint32_t index,
uint32_t value, uint32_t mask);
extern bool phm_cf_want_uvd_power_gating(struct pp_hwmgr *hwmgr);
extern bool phm_cf_want_vce_power_gating(struct pp_hwmgr *hwmgr);
extern bool phm_cf_want_microcode_fan_ctrl(struct pp_hwmgr *hwmgr);
extern int phm_trim_voltage_table(struct pp_atomctrl_voltage_table *vol_table);
extern int phm_get_svi2_mvdd_voltage_table(struct pp_atomctrl_voltage_table *vol_table, phm_ppt_v1_clock_voltage_dependency_table *dep_table);
extern int phm_get_svi2_vddci_voltage_table(struct pp_atomctrl_voltage_table *vol_table, phm_ppt_v1_clock_voltage_dependency_table *dep_table);
extern int phm_get_svi2_vdd_voltage_table(struct pp_atomctrl_voltage_table *vol_table, phm_ppt_v1_voltage_lookup_table *lookup_table);
extern void phm_trim_voltage_table_to_fit_state_table(uint32_t max_vol_steps, struct pp_atomctrl_voltage_table *vol_table);
extern int phm_reset_single_dpm_table(void *table, uint32_t count, int max);
extern void phm_setup_pcie_table_entry(void *table, uint32_t index, uint32_t pcie_gen, uint32_t pcie_lanes);
extern int32_t phm_get_dpm_level_enable_mask_value(void *table);
extern uint8_t phm_get_voltage_id(struct pp_atomctrl_voltage_table *voltage_table,
uint32_t voltage);
extern uint8_t phm_get_voltage_index(struct phm_ppt_v1_voltage_lookup_table *lookup_table, uint16_t voltage);
extern uint16_t phm_find_closest_vddci(struct pp_atomctrl_voltage_table *vddci_table, uint16_t vddci);
extern int phm_find_boot_level(void *table, uint32_t value, uint32_t *boot_level);
extern int phm_get_sclk_for_voltage_evv(struct pp_hwmgr *hwmgr, phm_ppt_v1_voltage_lookup_table *lookup_table,
uint16_t virtual_voltage_id, int32_t *sclk);
extern int phm_initializa_dynamic_state_adjustment_rule_settings(struct pp_hwmgr *hwmgr);
extern uint32_t phm_get_lowest_enabled_level(struct pp_hwmgr *hwmgr, uint32_t mask);
extern void phm_apply_dal_min_voltage_request(struct pp_hwmgr *hwmgr);
extern int phm_get_voltage_evv_on_sclk(struct pp_hwmgr *hwmgr, uint8_t voltage_type,
uint32_t sclk, uint16_t id, uint16_t *voltage);
extern uint32_t phm_set_field_to_u32(u32 offset, u32 original_data, u32 field, u32 size);
extern int phm_wait_on_register(struct pp_hwmgr *hwmgr, uint32_t index,
uint32_t value, uint32_t mask);
extern int phm_wait_on_indirect_register(struct pp_hwmgr *hwmgr,
uint32_t indirect_port,
uint32_t index,
uint32_t value,
uint32_t mask);
int phm_irq_process(struct amdgpu_device *adev,
struct amdgpu_irq_src *source,
struct amdgpu_iv_entry *entry);
int smu9_register_irq_handlers(struct pp_hwmgr *hwmgr);
void *smu_atom_get_data_table(void *dev, uint32_t table, uint16_t *size,
uint8_t *frev, uint8_t *crev);
int smu_get_voltage_dependency_table_ppt_v1(
const struct phm_ppt_v1_clock_voltage_dependency_table *allowed_dep_table,
struct phm_ppt_v1_clock_voltage_dependency_table *dep_table);
int smu_set_watermarks_for_clocks_ranges(void *wt_table,
struct dm_pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges);
#define PHM_FIELD_SHIFT(reg, field) reg##__##field##__SHIFT
#define PHM_FIELD_MASK(reg, field) reg##__##field##_MASK
#define PHM_SET_FIELD(origval, reg, field, fieldval) \
(((origval) & ~PHM_FIELD_MASK(reg, field)) | \
(PHM_FIELD_MASK(reg, field) & ((fieldval) << PHM_FIELD_SHIFT(reg, field))))
#define PHM_GET_FIELD(value, reg, field) \
(((value) & PHM_FIELD_MASK(reg, field)) >> \
PHM_FIELD_SHIFT(reg, field))
/* Operations on named fields. */
#define PHM_READ_FIELD(device, reg, field) \
PHM_GET_FIELD(cgs_read_register(device, mm##reg), reg, field)
#define PHM_READ_INDIRECT_FIELD(device, port, reg, field) \
PHM_GET_FIELD(cgs_read_ind_register(device, port, ix##reg), \
reg, field)
#define PHM_READ_VFPF_INDIRECT_FIELD(device, port, reg, field) \
PHM_GET_FIELD(cgs_read_ind_register(device, port, ix##reg), \
reg, field)
#define PHM_WRITE_FIELD(device, reg, field, fieldval) \
cgs_write_register(device, mm##reg, PHM_SET_FIELD( \
cgs_read_register(device, mm##reg), reg, field, fieldval))
#define PHM_WRITE_INDIRECT_FIELD(device, port, reg, field, fieldval) \
cgs_write_ind_register(device, port, ix##reg, \
PHM_SET_FIELD(cgs_read_ind_register(device, port, ix##reg), \
reg, field, fieldval))
#define PHM_WRITE_VFPF_INDIRECT_FIELD(device, port, reg, field, fieldval) \
cgs_write_ind_register(device, port, ix##reg, \
PHM_SET_FIELD(cgs_read_ind_register(device, port, ix##reg), \
reg, field, fieldval))
#define PHM_WAIT_INDIRECT_REGISTER_GIVEN_INDEX(hwmgr, port, index, value, mask) \
phm_wait_on_indirect_register(hwmgr, mm##port##_INDEX, index, value, mask)
#define PHM_WAIT_INDIRECT_REGISTER(hwmgr, port, reg, value, mask) \
PHM_WAIT_INDIRECT_REGISTER_GIVEN_INDEX(hwmgr, port, ix##reg, value, mask)
#define PHM_WAIT_INDIRECT_FIELD(hwmgr, port, reg, field, fieldval) \
PHM_WAIT_INDIRECT_REGISTER(hwmgr, port, reg, (fieldval) \
<< PHM_FIELD_SHIFT(reg, field), PHM_FIELD_MASK(reg, field))
#define PHM_WAIT_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, port, index, value, mask) \
phm_wait_for_indirect_register_unequal(hwmgr, \
mm##port##_INDEX, index, value, mask)
#define PHM_WAIT_INDIRECT_REGISTER_UNEQUAL(hwmgr, port, reg, value, mask) \
PHM_WAIT_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, port, ix##reg, value, mask)
#define PHM_WAIT_INDIRECT_FIELD_UNEQUAL(hwmgr, port, reg, field, fieldval) \
PHM_WAIT_INDIRECT_REGISTER_UNEQUAL(hwmgr, port, reg, \
(fieldval) << PHM_FIELD_SHIFT(reg, field), \
PHM_FIELD_MASK(reg, field) )
#define PHM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, \
port, index, value, mask) \
phm_wait_for_indirect_register_unequal(hwmgr, \
mm##port##_INDEX_11, index, value, mask)
#define PHM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL(hwmgr, port, reg, value, mask) \
PHM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, port, ix##reg, value, mask)
#define PHM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(hwmgr, port, reg, field, fieldval) \
PHM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL(hwmgr, port, reg, \
(fieldval) << PHM_FIELD_SHIFT(reg, field), \
PHM_FIELD_MASK(reg, field))
#define PHM_WAIT_VFPF_INDIRECT_REGISTER_GIVEN_INDEX(hwmgr, \
port, index, value, mask) \
phm_wait_on_indirect_register(hwmgr, \
mm##port##_INDEX_11, index, value, mask)
#define PHM_WAIT_VFPF_INDIRECT_REGISTER(hwmgr, port, reg, value, mask) \
PHM_WAIT_VFPF_INDIRECT_REGISTER_GIVEN_INDEX(hwmgr, port, ix##reg, value, mask)
#define PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr, port, reg, field, fieldval) \
PHM_WAIT_VFPF_INDIRECT_REGISTER(hwmgr, port, reg, \
(fieldval) << PHM_FIELD_SHIFT(reg, field), \
PHM_FIELD_MASK(reg, field))
#define PHM_WAIT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, \
index, value, mask) \
phm_wait_for_register_unequal(hwmgr, \
index, value, mask)
#define PHM_WAIT_REGISTER_UNEQUAL(hwmgr, reg, value, mask) \
PHM_WAIT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, \
mm##reg, value, mask)
#define PHM_WAIT_FIELD_UNEQUAL(hwmgr, reg, field, fieldval) \
PHM_WAIT_REGISTER_UNEQUAL(hwmgr, reg, \
(fieldval) << PHM_FIELD_SHIFT(reg, field), \
PHM_FIELD_MASK(reg, field))
#endif /* _SMU_HELPER_H_ */

View File

@@ -0,0 +1,231 @@
/*
* Copyright 2019 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 "tonga_baco.h"
#include "gmc/gmc_8_1_d.h"
#include "gmc/gmc_8_1_sh_mask.h"
#include "bif/bif_5_0_d.h"
#include "bif/bif_5_0_sh_mask.h"
#include "dce/dce_10_0_d.h"
#include "dce/dce_10_0_sh_mask.h"
#include "smu/smu_7_1_2_d.h"
#include "smu/smu_7_1_2_sh_mask.h"
static const struct baco_cmd_entry gpio_tbl[] =
{
{ CMD_WRITE, mmGPIOPAD_EN, 0, 0, 0, 0x0 },
{ CMD_WRITE, mmGPIOPAD_PD_EN, 0, 0, 0, 0x0 },
{ CMD_WRITE, mmGPIOPAD_PU_EN, 0, 0, 0, 0x0 },
{ CMD_WRITE, mmGPIOPAD_MASK, 0, 0, 0, 0xff77ffff },
{ CMD_WRITE, mmDC_GPIO_DVODATA_EN, 0, 0, 0, 0x0 },
{ CMD_WRITE, mmDC_GPIO_DVODATA_MASK, 0, 0, 0, 0xffffffff },
{ CMD_WRITE, mmDC_GPIO_GENERIC_EN, 0, 0, 0, 0x0 },
{ CMD_READMODIFYWRITE, mmDC_GPIO_GENERIC_MASK, 0, 0, 0, 0x03333333 },
{ CMD_WRITE, mmDC_GPIO_SYNCA_EN, 0, 0, 0, 0x0 },
{ CMD_READMODIFYWRITE, mmDC_GPIO_SYNCA_MASK, 0, 0, 0, 0x00001111 }
};
static const struct baco_cmd_entry enable_fb_req_rej_tbl[] =
{
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC0300024 },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x1, 0x0, 0, 0x1 },
{ CMD_WRITE, mmBIF_FB_EN, 0, 0, 0, 0x0 }
};
static const struct baco_cmd_entry use_bclk_tbl[] =
{
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL__SPLL_BYPASS_EN_MASK, CG_SPLL_FUNC_CNTL__SPLL_BYPASS_EN__SHIFT, 0, 0x1 },
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL_2 },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL_2__SPLL_BYPASS_CHG_MASK, CG_SPLL_FUNC_CNTL_2__SPLL_BYPASS_CHG__SHIFT, 0, 0x1 },
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_STATUS },
{ CMD_WAITFOR, mmGCK_SMC_IND_DATA, CG_SPLL_STATUS__SPLL_CHG_STATUS_MASK, 0, 0xffffffff, 0x2 },
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL_2 },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL_2__SPLL_BYPASS_CHG_MASK, CG_SPLL_FUNC_CNTL_2__SPLL_BYPASS_CHG__SHIFT, 0, 0x0 },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL_2__SPLL_CTLREQ_CHG_MASK, CG_SPLL_FUNC_CNTL_2__SPLL_CTLREQ_CHG__SHIFT, 0, 0x1 },
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_STATUS },
{ CMD_WAITFOR, mmGCK_SMC_IND_DATA, CG_SPLL_STATUS__SPLL_CHG_STATUS_MASK, 0, 0xffffffff, 0x2 },
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL_2 },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL_2__SPLL_CTLREQ_CHG_MASK, CG_SPLL_FUNC_CNTL_2__SPLL_CTLREQ_CHG__SHIFT, 0, 0x0 },
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC0500170 },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x4000000, 0x1a, 0, 0x1 },
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixMPLL_BYPASSCLK_SEL },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL_MASK, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL__SHIFT, 0, 0x2 },
{ CMD_READMODIFYWRITE, mmMPLL_CNTL_MODE, MPLL_CNTL_MODE__MPLL_SW_DIR_CONTROL_MASK, MPLL_CNTL_MODE__MPLL_SW_DIR_CONTROL__SHIFT, 0, 0x1 },
{ CMD_READMODIFYWRITE, mmMPLL_CNTL_MODE, MPLL_CNTL_MODE__MPLL_MCLK_SEL_MASK, MPLL_CNTL_MODE__MPLL_MCLK_SEL__SHIFT, 0, 0x0 }
};
static const struct baco_cmd_entry turn_off_plls_tbl[] =
{
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL__SPLL_RESET_MASK, CG_SPLL_FUNC_CNTL__SPLL_RESET__SHIFT, 0, 0x1 },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL__SPLL_PWRON_MASK, CG_SPLL_FUNC_CNTL__SPLL_PWRON__SHIFT, 0, 0x0 },
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC0500170 },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x2000000, 0x19, 0, 0x1 },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x8000000, 0x1b, 0, 0x0 },
{ CMD_READMODIFYWRITE, mmMPLL_CNTL_MODE, MPLL_CNTL_MODE__GLOBAL_MPLL_RESET_MASK, MPLL_CNTL_MODE__GLOBAL_MPLL_RESET__SHIFT, 0, 0x1 },
{ CMD_WRITE, mmMPLL_CONTROL, 0, 0, 0, 0x00000006 },
{ CMD_WRITE, mmMC_IO_RXCNTL_DPHY0_D0, 0, 0, 0, 0x00007740 },
{ CMD_WRITE, mmMC_IO_RXCNTL_DPHY0_D1, 0, 0, 0, 0x00007740 },
{ CMD_WRITE, mmMC_IO_RXCNTL_DPHY1_D0, 0, 0, 0, 0x00007740 },
{ CMD_WRITE, mmMC_IO_RXCNTL_DPHY1_D1, 0, 0, 0, 0x00007740 },
{ CMD_READMODIFYWRITE, mmMCLK_PWRMGT_CNTL, MCLK_PWRMGT_CNTL__MRDCK0_PDNB_MASK, MCLK_PWRMGT_CNTL__MRDCK0_PDNB__SHIFT, 0, 0x0 },
{ CMD_READMODIFYWRITE, mmMCLK_PWRMGT_CNTL, MCLK_PWRMGT_CNTL__MRDCK1_PDNB_MASK, MCLK_PWRMGT_CNTL__MRDCK1_PDNB__SHIFT, 0, 0x0 },
{ CMD_READMODIFYWRITE, mmMC_SEQ_CNTL_2, MC_SEQ_CNTL_2__DRST_PU_MASK, MC_SEQ_CNTL_2__DRST_PU__SHIFT, 0, 0x0 },
{ CMD_READMODIFYWRITE, mmMC_SEQ_CNTL_2, MC_SEQ_CNTL_2__DRST_PD_MASK, MC_SEQ_CNTL_2__DRST_PD__SHIFT, 0, 0x0 },
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_CLKPIN_CNTL_2 },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_CLKPIN_CNTL_2__FORCE_BIF_REFCLK_EN_MASK, CG_CLKPIN_CNTL_2__FORCE_BIF_REFCLK_EN__SHIFT, 0, 0x0 },
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixMPLL_BYPASSCLK_SEL },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL_MASK, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL__SHIFT, 0, 0x4 },
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixMISC_CLK_CTRL },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MISC_CLK_CTRL__DEEP_SLEEP_CLK_SEL_MASK, MISC_CLK_CTRL__DEEP_SLEEP_CLK_SEL__SHIFT, 0, 0x1 },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MISC_CLK_CTRL__ZCLK_SEL_MASK, MISC_CLK_CTRL__ZCLK_SEL__SHIFT, 0, 0x1 },
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_CLKPIN_CNTL },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_CLKPIN_CNTL__BCLK_AS_XCLK_MASK, CG_CLKPIN_CNTL__BCLK_AS_XCLK__SHIFT, 0, 0x0 },
{ CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixTHM_CLK_CNTL },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, THM_CLK_CNTL__CMON_CLK_SEL_MASK, THM_CLK_CNTL__CMON_CLK_SEL__SHIFT, 0, 0x1 },
{ CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, THM_CLK_CNTL__TMON_CLK_SEL_MASK, THM_CLK_CNTL__TMON_CLK_SEL__SHIFT, 0, 0x1 }
};
static const struct baco_cmd_entry enter_baco_tbl[] =
{
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_EN_MASK, BACO_CNTL__BACO_EN__SHIFT, 0, 0x01 },
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BIF_SCLK_SWITCH_MASK, BACO_CNTL__BACO_BIF_SCLK_SWITCH__SHIFT, 0, 0x01 },
{ CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_BIF_SCLK_SWITCH_MASK, 0, 5, 0x40000 },
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BCLK_OFF_MASK, BACO_CNTL__BACO_BCLK_OFF__SHIFT, 0, 0x01 },
{ CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_BCLK_OFF_MASK, 0, 5, 0x02 },
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ISO_DIS_MASK, BACO_CNTL__BACO_ISO_DIS__SHIFT, 0, 0x00 },
{ CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_ISO_DIS_MASK, 0, 5, 0x00 },
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ANA_ISO_DIS_MASK, BACO_CNTL__BACO_ANA_ISO_DIS__SHIFT, 0, 0x00 },
{ CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_ANA_ISO_DIS_MASK, 0, 5, 0x00 },
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, BACO_CNTL__BACO_POWER_OFF__SHIFT, 0, 0x01 },
{ CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, 0, 5, 0x08 },
{ CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_MODE_MASK, 0, 0xffffffff, 0x40 }
};
#define BACO_CNTL__PWRGOOD_MASK BACO_CNTL__PWRGOOD_GPIO_MASK+BACO_CNTL__PWRGOOD_MEM_MASK+BACO_CNTL__PWRGOOD_DVO_MASK
static const struct baco_cmd_entry exit_baco_tbl[] =
{
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_RESET_EN_MASK, BACO_CNTL__BACO_RESET_EN__SHIFT, 0, 0x01 },
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BCLK_OFF_MASK, BACO_CNTL__BACO_BCLK_OFF__SHIFT, 0, 0x00 },
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, BACO_CNTL__BACO_POWER_OFF__SHIFT, 0, 0x00 },
{ CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__PWRGOOD_BF_MASK, 0, 0xffffffff, 0x200 },
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ISO_DIS_MASK, BACO_CNTL__BACO_ISO_DIS__SHIFT, 0, 0x01 },
{ CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__PWRGOOD_MASK, 0, 5, 0x1c00 },
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ANA_ISO_DIS_MASK, BACO_CNTL__BACO_ANA_ISO_DIS__SHIFT, 0, 0x01 },
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BIF_SCLK_SWITCH_MASK, BACO_CNTL__BACO_BIF_SCLK_SWITCH__SHIFT, 0, 0x00 },
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_RESET_EN_MASK, BACO_CNTL__BACO_RESET_EN__SHIFT, 0, 0x00 },
{ CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__RCU_BIF_CONFIG_DONE_MASK, 0, 5, 0x100 },
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_EN_MASK, BACO_CNTL__BACO_EN__SHIFT, 0, 0x00 },
{ CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_MODE_MASK, 0, 0xffffffff, 0x00 }
};
static const struct baco_cmd_entry clean_baco_tbl[] =
{
{ CMD_WRITE, mmBIOS_SCRATCH_6, 0, 0, 0, 0 },
{ CMD_WRITE, mmBIOS_SCRATCH_7, 0, 0, 0, 0 }
};
static const struct baco_cmd_entry gpio_tbl_iceland[] =
{
{ CMD_WRITE, mmGPIOPAD_EN, 0, 0, 0, 0x0 },
{ CMD_WRITE, mmGPIOPAD_PD_EN, 0, 0, 0, 0x0 },
{ CMD_WRITE, mmGPIOPAD_PU_EN, 0, 0, 0, 0x0 },
{ CMD_WRITE, mmGPIOPAD_MASK, 0, 0, 0, 0xff77ffff }
};
static const struct baco_cmd_entry exit_baco_tbl_iceland[] =
{
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_RESET_EN_MASK, BACO_CNTL__BACO_RESET_EN__SHIFT, 0, 0x01 },
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BCLK_OFF_MASK, BACO_CNTL__BACO_BCLK_OFF__SHIFT, 0, 0x00 },
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, BACO_CNTL__BACO_POWER_OFF__SHIFT, 0, 0x00 },
{ CMD_DELAY_MS, 0, 0, 0, 20, 0 },
{ CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__PWRGOOD_BF_MASK, 0, 0xffffffff, 0x200 },
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ISO_DIS_MASK, BACO_CNTL__BACO_ISO_DIS__SHIFT, 0, 0x01 },
{ CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__PWRGOOD_MASK, 0, 5, 0x1c00 },
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ANA_ISO_DIS_MASK, BACO_CNTL__BACO_ANA_ISO_DIS__SHIFT, 0, 0x01 },
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BIF_SCLK_SWITCH_MASK, BACO_CNTL__BACO_BIF_SCLK_SWITCH__SHIFT, 0, 0x00 },
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_RESET_EN_MASK, BACO_CNTL__BACO_RESET_EN__SHIFT, 0, 0x00 },
{ CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__RCU_BIF_CONFIG_DONE_MASK, 0, 5, 0x100 },
{ CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_EN_MASK, BACO_CNTL__BACO_EN__SHIFT, 0, 0x00 },
{ CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_MODE_MASK, 0, 0xffffffff, 0x00 }
};
static const struct baco_cmd_entry clean_baco_tbl_iceland[] =
{
{ CMD_WRITE, mmBIOS_SCRATCH_7, 0, 0, 0, 0 }
};
int tonga_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state)
{
enum BACO_STATE cur_state;
smu7_baco_get_state(hwmgr, &cur_state);
if (cur_state == state)
/* aisc already in the target state */
return 0;
if (state == BACO_STATE_IN) {
if (hwmgr->chip_id == CHIP_TOPAZ)
baco_program_registers(hwmgr, gpio_tbl_iceland, ARRAY_SIZE(gpio_tbl_iceland));
else
baco_program_registers(hwmgr, gpio_tbl, ARRAY_SIZE(gpio_tbl));
baco_program_registers(hwmgr, enable_fb_req_rej_tbl,
ARRAY_SIZE(enable_fb_req_rej_tbl));
baco_program_registers(hwmgr, use_bclk_tbl, ARRAY_SIZE(use_bclk_tbl));
baco_program_registers(hwmgr, turn_off_plls_tbl,
ARRAY_SIZE(turn_off_plls_tbl));
if (baco_program_registers(hwmgr, enter_baco_tbl,
ARRAY_SIZE(enter_baco_tbl)))
return 0;
} else if (state == BACO_STATE_OUT) {
/* HW requires at least 20ms between regulator off and on */
msleep(20);
/* Execute Hardware BACO exit sequence */
if (hwmgr->chip_id == CHIP_TOPAZ) {
if (baco_program_registers(hwmgr, exit_baco_tbl_iceland,
ARRAY_SIZE(exit_baco_tbl_iceland))) {
if (baco_program_registers(hwmgr, clean_baco_tbl_iceland,
ARRAY_SIZE(clean_baco_tbl_iceland)))
return 0;
}
} else {
if (baco_program_registers(hwmgr, exit_baco_tbl,
ARRAY_SIZE(exit_baco_tbl))) {
if (baco_program_registers(hwmgr, clean_baco_tbl,
ARRAY_SIZE(clean_baco_tbl)))
return 0;
}
}
}
return -EINVAL;
}

View File

@@ -0,0 +1,29 @@
/*
* Copyright 2019 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.
*
*/
#ifndef __TONGA_BACO_H__
#define __TONGA_BACO_H__
#include "smu7_baco.h"
extern int tonga_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state);
#endif

View File

@@ -0,0 +1,121 @@
/*
* Copyright 2018 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 "soc15.h"
#include "soc15_hw_ip.h"
#include "vega10_ip_offset.h"
#include "soc15_common.h"
#include "vega10_inc.h"
#include "vega10_ppsmc.h"
#include "vega10_baco.h"
static const struct soc15_baco_cmd_entry pre_baco_tbl[] =
{
{CMD_READMODIFYWRITE, SOC15_REG_ENTRY(NBIF, 0, mmBIF_DOORBELL_CNTL), BIF_DOORBELL_CNTL__DOORBELL_MONITOR_EN_MASK, BIF_DOORBELL_CNTL__DOORBELL_MONITOR_EN__SHIFT, 0, 1},
{CMD_WRITE, SOC15_REG_ENTRY(NBIF, 0, mmBIF_FB_EN), 0, 0, 0, 0},
{CMD_READMODIFYWRITE, SOC15_REG_ENTRY(NBIF, 0, mmBACO_CNTL), BACO_CNTL__BACO_DSTATE_BYPASS_MASK, BACO_CNTL__BACO_DSTATE_BYPASS__SHIFT, 0, 1},
{CMD_READMODIFYWRITE, SOC15_REG_ENTRY(NBIF, 0, mmBACO_CNTL), BACO_CNTL__BACO_RST_INTR_MASK_MASK, BACO_CNTL__BACO_RST_INTR_MASK__SHIFT, 0, 1}
};
static const struct soc15_baco_cmd_entry enter_baco_tbl[] =
{
{CMD_WAITFOR, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__SOC_DOMAIN_IDLE_MASK, THM_BACO_CNTL__SOC_DOMAIN_IDLE__SHIFT, 0xffffffff, 0x80000000},
{CMD_READMODIFYWRITE, SOC15_REG_ENTRY(NBIF, 0, mmBACO_CNTL), BACO_CNTL__BACO_EN_MASK, BACO_CNTL__BACO_EN__SHIFT, 0, 1},
{CMD_READMODIFYWRITE, SOC15_REG_ENTRY(NBIF, 0, mmBACO_CNTL), BACO_CNTL__BACO_BIF_LCLK_SWITCH_MASK, BACO_CNTL__BACO_BIF_LCLK_SWITCH__SHIFT, 0, 1},
{CMD_READMODIFYWRITE, SOC15_REG_ENTRY(NBIF, 0, mmBACO_CNTL), BACO_CNTL__BACO_DUMMY_EN_MASK, BACO_CNTL__BACO_DUMMY_EN__SHIFT, 0, 1},
{CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_SOC_VDCI_RESET_MASK, THM_BACO_CNTL__BACO_SOC_VDCI_RESET__SHIFT, 0, 1},
{CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_SMNCLK_MUX_MASK, THM_BACO_CNTL__BACO_SMNCLK_MUX__SHIFT,0, 1},
{CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_ISO_EN_MASK, THM_BACO_CNTL__BACO_ISO_EN__SHIFT, 0, 1},
{CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_AEB_ISO_EN_MASK, THM_BACO_CNTL__BACO_AEB_ISO_EN__SHIFT,0, 1},
{CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_ANA_ISO_EN_MASK, THM_BACO_CNTL__BACO_ANA_ISO_EN__SHIFT, 0, 1},
{CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_SOC_REFCLK_OFF_MASK, THM_BACO_CNTL__BACO_SOC_REFCLK_OFF__SHIFT, 0, 1},
{CMD_READMODIFYWRITE, SOC15_REG_ENTRY(NBIF, 0, mmBACO_CNTL), BACO_CNTL__BACO_POWER_OFF_MASK, BACO_CNTL__BACO_POWER_OFF__SHIFT, 0, 1},
{CMD_DELAY_MS, 0, 0, 0, 0, 0, 0, 5, 0},
{CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_RESET_EN_MASK, THM_BACO_CNTL__BACO_RESET_EN__SHIFT, 0, 1},
{CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_PWROKRAW_CNTL_MASK, THM_BACO_CNTL__BACO_PWROKRAW_CNTL__SHIFT, 0, 0},
{CMD_WAITFOR, SOC15_REG_ENTRY(NBIF, 0, mmBACO_CNTL), BACO_CNTL__BACO_MODE_MASK, BACO_CNTL__BACO_MODE__SHIFT, 0xffffffff, 0x100}
};
static const struct soc15_baco_cmd_entry exit_baco_tbl[] =
{
{CMD_READMODIFYWRITE, SOC15_REG_ENTRY(NBIF, 0, mmBACO_CNTL), BACO_CNTL__BACO_POWER_OFF_MASK, BACO_CNTL__BACO_POWER_OFF__SHIFT, 0, 0},
{CMD_DELAY_MS, 0, 0, 0, 0, 0, 0, 10,0},
{CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_SOC_REFCLK_OFF_MASK, THM_BACO_CNTL__BACO_SOC_REFCLK_OFF__SHIFT, 0,0},
{CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_ANA_ISO_EN_MASK, THM_BACO_CNTL__BACO_ANA_ISO_EN__SHIFT, 0, 0},
{CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_AEB_ISO_EN_MASK, THM_BACO_CNTL__BACO_AEB_ISO_EN__SHIFT,0, 0},
{CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_ISO_EN_MASK, THM_BACO_CNTL__BACO_ISO_EN__SHIFT, 0, 0},
{CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_PWROKRAW_CNTL_MASK, THM_BACO_CNTL__BACO_PWROKRAW_CNTL__SHIFT, 0, 1},
{CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_SMNCLK_MUX_MASK, THM_BACO_CNTL__BACO_SMNCLK_MUX__SHIFT, 0, 0},
{CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_SOC_VDCI_RESET_MASK, THM_BACO_CNTL__BACO_SOC_VDCI_RESET__SHIFT, 0, 0},
{CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_EXIT_MASK, THM_BACO_CNTL__BACO_EXIT__SHIFT, 0, 1},
{CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_RESET_EN_MASK, THM_BACO_CNTL__BACO_RESET_EN__SHIFT, 0, 0},
{CMD_WAITFOR, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_EXIT_MASK, 0, 0xffffffff, 0},
{CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_SB_AXI_FENCE_MASK, THM_BACO_CNTL__BACO_SB_AXI_FENCE__SHIFT, 0, 0},
{CMD_READMODIFYWRITE, SOC15_REG_ENTRY(NBIF, 0, mmBACO_CNTL), BACO_CNTL__BACO_DUMMY_EN_MASK, BACO_CNTL__BACO_DUMMY_EN__SHIFT, 0, 0},
{CMD_READMODIFYWRITE, SOC15_REG_ENTRY(NBIF, 0, mmBACO_CNTL), BACO_CNTL__BACO_BIF_LCLK_SWITCH_MASK ,BACO_CNTL__BACO_BIF_LCLK_SWITCH__SHIFT, 0, 0},
{CMD_READMODIFYWRITE, SOC15_REG_ENTRY(NBIF, 0, mmBACO_CNTL), BACO_CNTL__BACO_EN_MASK , BACO_CNTL__BACO_EN__SHIFT, 0,0},
{CMD_WAITFOR, SOC15_REG_ENTRY(NBIF, 0, mmBACO_CNTL), BACO_CNTL__BACO_MODE_MASK, 0, 0xffffffff, 0}
};
static const struct soc15_baco_cmd_entry clean_baco_tbl[] =
{
{CMD_WRITE, SOC15_REG_ENTRY(NBIF, 0, mmBIOS_SCRATCH_6), 0, 0, 0, 0},
{CMD_WRITE, SOC15_REG_ENTRY(NBIF, 0, mmBIOS_SCRATCH_7), 0, 0, 0, 0},
};
int vega10_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state)
{
enum BACO_STATE cur_state;
smu9_baco_get_state(hwmgr, &cur_state);
if (cur_state == state)
/* aisc already in the target state */
return 0;
if (state == BACO_STATE_IN) {
if (soc15_baco_program_registers(hwmgr, pre_baco_tbl,
ARRAY_SIZE(pre_baco_tbl))) {
if (smum_send_msg_to_smc(hwmgr, PPSMC_MSG_EnterBaco, NULL))
return -EINVAL;
if (soc15_baco_program_registers(hwmgr, enter_baco_tbl,
ARRAY_SIZE(enter_baco_tbl)))
return 0;
}
} else if (state == BACO_STATE_OUT) {
/* HW requires at least 20ms between regulator off and on */
msleep(20);
/* Execute Hardware BACO exit sequence */
if (soc15_baco_program_registers(hwmgr, exit_baco_tbl,
ARRAY_SIZE(exit_baco_tbl))) {
if (soc15_baco_program_registers(hwmgr, clean_baco_tbl,
ARRAY_SIZE(clean_baco_tbl)))
return 0;
}
}
return -EINVAL;
}

View File

@@ -0,0 +1,29 @@
/*
* Copyright 2018 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.
*
*/
#ifndef __VEGA10_BACO_H__
#define __VEGA10_BACO_H__
#include "smu9_baco.h"
extern int vega10_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,446 @@
/*
* 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.
*
*/
#ifndef _VEGA10_HWMGR_H_
#define _VEGA10_HWMGR_H_
#include "hwmgr.h"
#include "smu9_driver_if.h"
#include "ppatomctrl.h"
#include "ppatomfwctrl.h"
#include "vega10_ppsmc.h"
#include "vega10_powertune.h"
#define VEGA10_MAX_HARDWARE_POWERLEVELS 2
#define WaterMarksExist 1
#define WaterMarksLoaded 2
enum {
GNLD_DPM_PREFETCHER = 0,
GNLD_DPM_GFXCLK,
GNLD_DPM_UCLK,
GNLD_DPM_SOCCLK,
GNLD_DPM_UVD,
GNLD_DPM_VCE,
GNLD_ULV,
GNLD_DPM_MP0CLK,
GNLD_DPM_LINK,
GNLD_DPM_DCEFCLK,
GNLD_AVFS,
GNLD_DS_GFXCLK,
GNLD_DS_SOCCLK,
GNLD_DS_LCLK,
GNLD_PPT,
GNLD_TDC,
GNLD_THERMAL,
GNLD_GFX_PER_CU_CG,
GNLD_RM,
GNLD_DS_DCEFCLK,
GNLD_ACDC,
GNLD_VR0HOT,
GNLD_VR1HOT,
GNLD_FW_CTF,
GNLD_LED_DISPLAY,
GNLD_FAN_CONTROL,
GNLD_FEATURE_FAST_PPT_BIT,
GNLD_DIDT,
GNLD_ACG,
GNLD_PCC_LIMIT,
GNLD_FEATURES_MAX
};
#define GNLD_DPM_MAX (GNLD_DPM_DCEFCLK + 1)
#define SMC_DPM_FEATURES 0x30F
struct smu_features {
bool supported;
bool enabled;
uint32_t smu_feature_id;
uint32_t smu_feature_bitmap;
};
struct vega10_performance_level {
uint32_t soc_clock;
uint32_t gfx_clock;
uint32_t mem_clock;
};
struct vega10_bacos {
uint32_t baco_flags;
/* struct vega10_performance_level performance_level; */
};
struct vega10_uvd_clocks {
uint32_t vclk;
uint32_t dclk;
};
struct vega10_vce_clocks {
uint32_t evclk;
uint32_t ecclk;
};
struct vega10_power_state {
uint32_t magic;
struct vega10_uvd_clocks uvd_clks;
struct vega10_vce_clocks vce_clks;
uint16_t performance_level_count;
bool dc_compatible;
uint32_t sclk_threshold;
struct vega10_performance_level performance_levels[VEGA10_MAX_HARDWARE_POWERLEVELS];
};
struct vega10_dpm_level {
bool enabled;
uint32_t value;
uint32_t param1;
};
#define VEGA10_MAX_DEEPSLEEP_DIVIDER_ID 5
#define MAX_REGULAR_DPM_NUMBER 8
#define MAX_PCIE_CONF 2
#define VEGA10_MINIMUM_ENGINE_CLOCK 2500
struct vega10_dpm_state {
uint32_t soft_min_level;
uint32_t soft_max_level;
uint32_t hard_min_level;
uint32_t hard_max_level;
};
struct vega10_single_dpm_table {
uint32_t count;
struct vega10_dpm_state dpm_state;
struct vega10_dpm_level dpm_levels[MAX_REGULAR_DPM_NUMBER];
};
struct vega10_pcie_table {
uint16_t count;
uint8_t pcie_gen[MAX_PCIE_CONF];
uint8_t pcie_lane[MAX_PCIE_CONF];
uint32_t lclk[MAX_PCIE_CONF];
};
struct vega10_dpm_table {
struct vega10_single_dpm_table soc_table;
struct vega10_single_dpm_table gfx_table;
struct vega10_single_dpm_table mem_table;
struct vega10_single_dpm_table eclk_table;
struct vega10_single_dpm_table vclk_table;
struct vega10_single_dpm_table dclk_table;
struct vega10_single_dpm_table dcef_table;
struct vega10_single_dpm_table pixel_table;
struct vega10_single_dpm_table display_table;
struct vega10_single_dpm_table phy_table;
struct vega10_pcie_table pcie_table;
};
#define VEGA10_MAX_LEAKAGE_COUNT 8
struct vega10_leakage_voltage {
uint16_t count;
uint16_t leakage_id[VEGA10_MAX_LEAKAGE_COUNT];
uint16_t actual_voltage[VEGA10_MAX_LEAKAGE_COUNT];
};
struct vega10_display_timing {
uint32_t min_clock_in_sr;
uint32_t num_existing_displays;
};
struct vega10_dpmlevel_enable_mask {
uint32_t uvd_dpm_enable_mask;
uint32_t vce_dpm_enable_mask;
uint32_t acp_dpm_enable_mask;
uint32_t samu_dpm_enable_mask;
uint32_t sclk_dpm_enable_mask;
uint32_t mclk_dpm_enable_mask;
};
struct vega10_vbios_boot_state {
bool bsoc_vddc_lock;
uint16_t vddc;
uint16_t vddci;
uint16_t mvddc;
uint16_t vdd_gfx;
uint32_t gfx_clock;
uint32_t mem_clock;
uint32_t soc_clock;
uint32_t dcef_clock;
};
struct vega10_smc_state_table {
uint32_t soc_boot_level;
uint32_t gfx_boot_level;
uint32_t dcef_boot_level;
uint32_t mem_boot_level;
uint32_t uvd_boot_level;
uint32_t vce_boot_level;
uint32_t gfx_max_level;
uint32_t mem_max_level;
uint32_t soc_max_level;
uint8_t vr_hot_gpio;
uint8_t ac_dc_gpio;
uint8_t therm_out_gpio;
uint8_t therm_out_polarity;
uint8_t therm_out_mode;
PPTable_t pp_table;
Watermarks_t water_marks_table;
AvfsTable_t avfs_table;
AvfsFuseOverride_t avfs_fuse_override_table;
};
struct vega10_mclk_latency_entries {
uint32_t frequency;
uint32_t latency;
};
struct vega10_mclk_latency_table {
uint32_t count;
struct vega10_mclk_latency_entries entries[MAX_REGULAR_DPM_NUMBER];
};
struct vega10_registry_data {
uint8_t ac_dc_switch_gpio_support;
uint8_t avfs_support;
uint8_t cac_support;
uint8_t clock_stretcher_support;
uint8_t db_ramping_support;
uint8_t didt_mode;
uint8_t didt_support;
uint8_t edc_didt_support;
uint8_t dynamic_state_patching_support;
uint8_t enable_pkg_pwr_tracking_feature;
uint8_t enable_tdc_limit_feature;
uint32_t fast_watermark_threshold;
uint8_t force_dpm_high;
uint8_t fuzzy_fan_control_support;
uint8_t long_idle_baco_support;
uint8_t mclk_dpm_key_disabled;
uint8_t od_state_in_dc_support;
uint8_t pcieLaneOverride;
uint8_t pcieSpeedOverride;
uint32_t pcieClockOverride;
uint8_t pcie_dpm_key_disabled;
uint8_t dcefclk_dpm_key_disabled;
uint8_t power_containment_support;
uint8_t ppt_support;
uint8_t prefetcher_dpm_key_disabled;
uint8_t quick_transition_support;
uint8_t regulator_hot_gpio_support;
uint8_t sclk_deep_sleep_support;
uint8_t sclk_dpm_key_disabled;
uint8_t sclk_from_vbios;
uint8_t sclk_throttle_low_notification;
uint8_t show_baco_dbg_info;
uint8_t skip_baco_hardware;
uint8_t socclk_dpm_key_disabled;
uint8_t spll_shutdown_support;
uint8_t sq_ramping_support;
uint32_t stable_pstate_sclk_dpm_percentage;
uint8_t tcp_ramping_support;
uint8_t tdc_support;
uint8_t td_ramping_support;
uint8_t dbr_ramping_support;
uint8_t gc_didt_support;
uint8_t psm_didt_support;
uint8_t thermal_out_gpio_support;
uint8_t thermal_support;
uint8_t fw_ctf_enabled;
uint8_t fan_control_support;
uint8_t ulps_support;
uint8_t ulv_support;
uint32_t vddc_vddci_delta;
uint8_t odn_feature_enable;
uint8_t disable_water_mark;
uint8_t zrpm_stop_temp;
uint8_t zrpm_start_temp;
uint8_t led_dpm_enabled;
uint8_t vr0hot_enabled;
uint8_t vr1hot_enabled;
};
struct vega10_odn_clock_voltage_dependency_table {
uint32_t count;
struct phm_ppt_v1_clock_voltage_dependency_record entries[MAX_REGULAR_DPM_NUMBER];
};
struct vega10_odn_vddc_lookup_table {
uint32_t count;
struct phm_ppt_v1_voltage_lookup_record entries[MAX_REGULAR_DPM_NUMBER];
};
struct vega10_odn_dpm_table {
struct vega10_odn_clock_voltage_dependency_table vdd_dep_on_sclk;
struct vega10_odn_clock_voltage_dependency_table vdd_dep_on_mclk;
struct vega10_odn_clock_voltage_dependency_table vdd_dep_on_socclk;
struct vega10_odn_vddc_lookup_table vddc_lookup_table;
uint32_t max_vddc;
uint32_t min_vddc;
};
struct vega10_odn_fan_table {
uint32_t target_fan_speed;
uint32_t target_temperature;
uint32_t min_performance_clock;
uint32_t min_fan_limit;
};
struct vega10_hwmgr {
struct vega10_dpm_table dpm_table;
struct vega10_dpm_table golden_dpm_table;
struct vega10_registry_data registry_data;
struct vega10_vbios_boot_state vbios_boot_state;
struct vega10_mclk_latency_table mclk_latency_table;
struct vega10_leakage_voltage vddc_leakage;
uint32_t vddc_control;
struct pp_atomfwctrl_voltage_table vddc_voltage_table;
uint32_t mvdd_control;
struct pp_atomfwctrl_voltage_table mvdd_voltage_table;
uint32_t vddci_control;
struct pp_atomfwctrl_voltage_table vddci_voltage_table;
uint32_t active_auto_throttle_sources;
uint32_t water_marks_bitmap;
struct vega10_bacos bacos;
struct vega10_odn_dpm_table odn_dpm_table;
struct vega10_odn_fan_table odn_fan_table;
/* ---- General data ---- */
uint8_t need_update_dpm_table;
bool cac_enabled;
bool battery_state;
bool is_tlu_enabled;
uint32_t low_sclk_interrupt_threshold;
uint32_t total_active_cus;
struct vega10_display_timing display_timing;
/* ---- Vega10 Dyn Register Settings ---- */
uint32_t debug_settings;
uint32_t lowest_uclk_reserved_for_ulv;
uint32_t gfxclk_average_alpha;
uint32_t socclk_average_alpha;
uint32_t uclk_average_alpha;
uint32_t gfx_activity_average_alpha;
uint32_t display_voltage_mode;
uint32_t dcef_clk_quad_eqn_a;
uint32_t dcef_clk_quad_eqn_b;
uint32_t dcef_clk_quad_eqn_c;
uint32_t disp_clk_quad_eqn_a;
uint32_t disp_clk_quad_eqn_b;
uint32_t disp_clk_quad_eqn_c;
uint32_t pixel_clk_quad_eqn_a;
uint32_t pixel_clk_quad_eqn_b;
uint32_t pixel_clk_quad_eqn_c;
uint32_t phy_clk_quad_eqn_a;
uint32_t phy_clk_quad_eqn_b;
uint32_t phy_clk_quad_eqn_c;
/* ---- Thermal Temperature Setting ---- */
struct vega10_dpmlevel_enable_mask dpm_level_enable_mask;
/* ---- Power Gating States ---- */
bool uvd_power_gated;
bool vce_power_gated;
bool need_long_memory_training;
/* Internal settings to apply the application power optimization parameters */
uint32_t disable_dpm_mask;
/* ---- SMU9 ---- */
struct smu_features smu_features[GNLD_FEATURES_MAX];
struct vega10_smc_state_table smc_state_table;
uint32_t config_telemetry;
uint32_t acg_loop_state;
uint32_t mem_channels;
uint8_t custom_profile_mode[4];
};
#define VEGA10_DPM2_NEAR_TDP_DEC 10
#define VEGA10_DPM2_ABOVE_SAFE_INC 5
#define VEGA10_DPM2_BELOW_SAFE_INC 20
#define VEGA10_DPM2_LTA_WINDOW_SIZE 7
#define VEGA10_DPM2_LTS_TRUNCATE 0
#define VEGA10_DPM2_TDP_SAFE_LIMIT_PERCENT 80
#define VEGA10_DPM2_MAXPS_PERCENT_M 90
#define VEGA10_DPM2_MAXPS_PERCENT_H 90
#define VEGA10_DPM2_PWREFFICIENCYRATIO_MARGIN 50
#define VEGA10_DPM2_SQ_RAMP_MAX_POWER 0x3FFF
#define VEGA10_DPM2_SQ_RAMP_MIN_POWER 0x12
#define VEGA10_DPM2_SQ_RAMP_MAX_POWER_DELTA 0x15
#define VEGA10_DPM2_SQ_RAMP_SHORT_TERM_INTERVAL_SIZE 0x1E
#define VEGA10_DPM2_SQ_RAMP_LONG_TERM_INTERVAL_RATIO 0xF
#define VEGA10_VOLTAGE_CONTROL_NONE 0x0
#define VEGA10_VOLTAGE_CONTROL_BY_GPIO 0x1
#define VEGA10_VOLTAGE_CONTROL_BY_SVID2 0x2
#define VEGA10_VOLTAGE_CONTROL_MERGED 0x3
/* To convert to Q8.8 format for firmware */
#define VEGA10_Q88_FORMAT_CONVERSION_UNIT 256
#define VEGA10_UNUSED_GPIO_PIN 0x7F
#define VEGA10_THERM_OUT_MODE_DISABLE 0x0
#define VEGA10_THERM_OUT_MODE_THERM_ONLY 0x1
#define VEGA10_THERM_OUT_MODE_THERM_VRHOT 0x2
#define PPVEGA10_VEGA10DISPLAYVOLTAGEMODE_DFLT 0xffffffff
#define PPREGKEY_VEGA10QUADRATICEQUATION_DFLT 0xffffffff
#define PPVEGA10_VEGA10GFXCLKAVERAGEALPHA_DFLT 25 /* 10% * 255 = 25 */
#define PPVEGA10_VEGA10SOCCLKAVERAGEALPHA_DFLT 25 /* 10% * 255 = 25 */
#define PPVEGA10_VEGA10UCLKCLKAVERAGEALPHA_DFLT 25 /* 10% * 255 = 25 */
#define PPVEGA10_VEGA10GFXACTIVITYAVERAGEALPHA_DFLT 25 /* 10% * 255 = 25 */
#define VEGA10_UMD_PSTATE_GFXCLK_LEVEL 0x3
#define VEGA10_UMD_PSTATE_SOCCLK_LEVEL 0x3
#define VEGA10_UMD_PSTATE_MCLK_LEVEL 0x2
extern int tonga_initializa_dynamic_state_adjustment_rule_settings(struct pp_hwmgr *hwmgr);
extern int tonga_hwmgr_backend_fini(struct pp_hwmgr *hwmgr);
extern int tonga_get_mc_microcode_version (struct pp_hwmgr *hwmgr);
extern int tonga_notify_smc_display_config_after_ps_adjustment(struct pp_hwmgr *hwmgr);
extern int tonga_notify_smc_display_change(struct pp_hwmgr *hwmgr, bool has_display);
int vega10_update_vce_dpm(struct pp_hwmgr *hwmgr, const void *input);
int vega10_update_uvd_dpm(struct pp_hwmgr *hwmgr, bool bgate);
int vega10_update_samu_dpm(struct pp_hwmgr *hwmgr, bool bgate);
int vega10_update_acp_dpm(struct pp_hwmgr *hwmgr, bool bgate);
int vega10_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable);
#endif /* _VEGA10_HWMGR_H_ */

View File

@@ -0,0 +1,43 @@
/*
* 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.
*
*/
#ifndef VEGA10_INC_H
#define VEGA10_INC_H
#include "asic_reg/thm/thm_9_0_default.h"
#include "asic_reg/thm/thm_9_0_offset.h"
#include "asic_reg/thm/thm_9_0_sh_mask.h"
#include "asic_reg/mp/mp_9_0_offset.h"
#include "asic_reg/mp/mp_9_0_sh_mask.h"
#include "asic_reg/gc/gc_9_0_default.h"
#include "asic_reg/gc/gc_9_0_offset.h"
#include "asic_reg/gc/gc_9_0_sh_mask.h"
#include "asic_reg/nbio/nbio_6_1_default.h"
#include "asic_reg/nbio/nbio_6_1_offset.h"
#include "asic_reg/nbio/nbio_6_1_sh_mask.h"
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,82 @@
/*
* 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.
*
*/
#ifndef _VEGA10_POWERTUNE_H_
#define _VEGA10_POWERTUNE_H_
enum vega10_pt_config_reg_type {
VEGA10_CONFIGREG_MMR = 0,
VEGA10_CONFIGREG_SMC_IND,
VEGA10_CONFIGREG_DIDT_IND,
VEGA10_CONFIGREG_CACHE,
VEGA10_CONFIGREG_MAX
};
enum vega10_didt_config_reg_type {
VEGA10_CONFIGREG_DIDT = 0,
VEGA10_CONFIGREG_GCCAC,
VEGA10_CONFIGREG_SECAC
};
/* PowerContainment Features */
#define POWERCONTAINMENT_FEATURE_DTE 0x00000001
#define POWERCONTAINMENT_FEATURE_TDCLimit 0x00000002
#define POWERCONTAINMENT_FEATURE_PkgPwrLimit 0x00000004
struct vega10_pt_config_reg {
uint32_t offset;
uint32_t mask;
uint32_t shift;
uint32_t value;
enum vega10_pt_config_reg_type type;
};
struct vega10_didt_config_reg {
uint32_t offset;
uint32_t mask;
uint32_t shift;
uint32_t value;
};
struct vega10_pt_defaults {
uint8_t SviLoadLineEn;
uint8_t SviLoadLineVddC;
uint8_t TDC_VDDC_ThrottleReleaseLimitPerc;
uint8_t TDC_MAWt;
uint8_t TdcWaterfallCtl;
uint8_t DTEAmbientTempBase;
};
void vega10_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr);
int vega10_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr);
int vega10_populate_pm_fuses(struct pp_hwmgr *hwmgr);
int vega10_enable_smc_cac(struct pp_hwmgr *hwmgr);
int vega10_enable_power_containment(struct pp_hwmgr *hwmgr);
int vega10_set_power_limit(struct pp_hwmgr *hwmgr, uint32_t n);
int vega10_power_control_set_level(struct pp_hwmgr *hwmgr);
int vega10_disable_power_containment(struct pp_hwmgr *hwmgr);
int vega10_enable_didt_config(struct pp_hwmgr *hwmgr);
int vega10_disable_didt_config(struct pp_hwmgr *hwmgr);
#endif /* _VEGA10_POWERTUNE_H_ */

View File

@@ -0,0 +1,445 @@
/*
* 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.
*
*/
#ifndef _VEGA10_PPTABLE_H_
#define _VEGA10_PPTABLE_H_
#pragma pack(push, 1)
#define ATOM_VEGA10_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK 0x0f
#define ATOM_VEGA10_PP_FANPARAMETERS_NOFAN 0x80
#define ATOM_VEGA10_PP_THERMALCONTROLLER_NONE 0
#define ATOM_VEGA10_PP_THERMALCONTROLLER_LM96163 17
#define ATOM_VEGA10_PP_THERMALCONTROLLER_VEGA10 24
#define ATOM_VEGA10_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL 0x89
#define ATOM_VEGA10_PP_THERMALCONTROLLER_EMC2103_WITH_INTERNAL 0x8D
#define ATOM_VEGA10_PP_PLATFORM_CAP_POWERPLAY 0x1
#define ATOM_VEGA10_PP_PLATFORM_CAP_SBIOSPOWERSOURCE 0x2
#define ATOM_VEGA10_PP_PLATFORM_CAP_HARDWAREDC 0x4
#define ATOM_VEGA10_PP_PLATFORM_CAP_BACO 0x8
#define ATOM_VEGA10_PP_PLATFORM_COMBINE_PCC_WITH_THERMAL_SIGNAL 0x10
/* ATOM_PPLIB_NONCLOCK_INFO::usClassification */
#define ATOM_PPLIB_CLASSIFICATION_UI_MASK 0x0007
#define ATOM_PPLIB_CLASSIFICATION_UI_SHIFT 0
#define ATOM_PPLIB_CLASSIFICATION_UI_NONE 0
#define ATOM_PPLIB_CLASSIFICATION_UI_BATTERY 1
#define ATOM_PPLIB_CLASSIFICATION_UI_BALANCED 3
#define ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE 5
/* 2, 4, 6, 7 are reserved */
#define ATOM_PPLIB_CLASSIFICATION_BOOT 0x0008
#define ATOM_PPLIB_CLASSIFICATION_THERMAL 0x0010
#define ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE 0x0020
#define ATOM_PPLIB_CLASSIFICATION_REST 0x0040
#define ATOM_PPLIB_CLASSIFICATION_FORCED 0x0080
#define ATOM_PPLIB_CLASSIFICATION_ACPI 0x1000
/* ATOM_PPLIB_NONCLOCK_INFO::usClassification2 */
#define ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2 0x0001
#define ATOM_Vega10_DISALLOW_ON_DC 0x00004000
#define ATOM_Vega10_ENABLE_VARIBRIGHT 0x00008000
#define ATOM_Vega10_TABLE_REVISION_VEGA10 8
#define ATOM_Vega10_VoltageMode_AVFS_Interpolate 0
#define ATOM_Vega10_VoltageMode_AVFS_WorstCase 1
#define ATOM_Vega10_VoltageMode_Static 2
typedef struct _ATOM_Vega10_POWERPLAYTABLE {
struct atom_common_table_header sHeader;
UCHAR ucTableRevision;
USHORT usTableSize; /* the size of header structure */
ULONG ulGoldenPPID; /* PPGen use only */
ULONG ulGoldenRevision; /* PPGen use only */
USHORT usFormatID; /* PPGen use only */
ULONG ulPlatformCaps; /* See ATOM_Vega10_CAPS_* */
ULONG ulMaxODEngineClock; /* For Overdrive. */
ULONG ulMaxODMemoryClock; /* For Overdrive. */
USHORT usPowerControlLimit;
USHORT usUlvVoltageOffset; /* in mv units */
USHORT usUlvSmnclkDid;
USHORT usUlvMp1clkDid;
USHORT usUlvGfxclkBypass;
USHORT usGfxclkSlewRate;
UCHAR ucGfxVoltageMode;
UCHAR ucSocVoltageMode;
UCHAR ucUclkVoltageMode;
UCHAR ucUvdVoltageMode;
UCHAR ucVceVoltageMode;
UCHAR ucMp0VoltageMode;
UCHAR ucDcefVoltageMode;
USHORT usStateArrayOffset; /* points to ATOM_Vega10_State_Array */
USHORT usFanTableOffset; /* points to ATOM_Vega10_Fan_Table */
USHORT usThermalControllerOffset; /* points to ATOM_Vega10_Thermal_Controller */
USHORT usSocclkDependencyTableOffset; /* points to ATOM_Vega10_SOCCLK_Dependency_Table */
USHORT usMclkDependencyTableOffset; /* points to ATOM_Vega10_MCLK_Dependency_Table */
USHORT usGfxclkDependencyTableOffset; /* points to ATOM_Vega10_GFXCLK_Dependency_Table */
USHORT usDcefclkDependencyTableOffset; /* points to ATOM_Vega10_DCEFCLK_Dependency_Table */
USHORT usVddcLookupTableOffset; /* points to ATOM_Vega10_Voltage_Lookup_Table */
USHORT usVddmemLookupTableOffset; /* points to ATOM_Vega10_Voltage_Lookup_Table */
USHORT usMMDependencyTableOffset; /* points to ATOM_Vega10_MM_Dependency_Table */
USHORT usVCEStateTableOffset; /* points to ATOM_Vega10_VCE_State_Table */
USHORT usReserve; /* No PPM Support for Vega10 */
USHORT usPowerTuneTableOffset; /* points to ATOM_Vega10_PowerTune_Table */
USHORT usHardLimitTableOffset; /* points to ATOM_Vega10_Hard_Limit_Table */
USHORT usVddciLookupTableOffset; /* points to ATOM_Vega10_Voltage_Lookup_Table */
USHORT usPCIETableOffset; /* points to ATOM_Vega10_PCIE_Table */
USHORT usPixclkDependencyTableOffset; /* points to ATOM_Vega10_PIXCLK_Dependency_Table */
USHORT usDispClkDependencyTableOffset; /* points to ATOM_Vega10_DISPCLK_Dependency_Table */
USHORT usPhyClkDependencyTableOffset; /* points to ATOM_Vega10_PHYCLK_Dependency_Table */
} ATOM_Vega10_POWERPLAYTABLE;
typedef struct _ATOM_Vega10_State {
UCHAR ucSocClockIndexHigh;
UCHAR ucSocClockIndexLow;
UCHAR ucGfxClockIndexHigh;
UCHAR ucGfxClockIndexLow;
UCHAR ucMemClockIndexHigh;
UCHAR ucMemClockIndexLow;
USHORT usClassification;
ULONG ulCapsAndSettings;
USHORT usClassification2;
} ATOM_Vega10_State;
typedef struct _ATOM_Vega10_State_Array {
UCHAR ucRevId;
UCHAR ucNumEntries; /* Number of entries. */
ATOM_Vega10_State states[1]; /* Dynamically allocate entries. */
} ATOM_Vega10_State_Array;
typedef struct _ATOM_Vega10_CLK_Dependency_Record {
ULONG ulClk; /* Frequency of Clock */
UCHAR ucVddInd; /* Base voltage */
} ATOM_Vega10_CLK_Dependency_Record;
typedef struct _ATOM_Vega10_GFXCLK_Dependency_Record {
ULONG ulClk; /* Clock Frequency */
UCHAR ucVddInd; /* SOC_VDD index */
USHORT usCKSVOffsetandDisable; /* Bits 0~30: Voltage offset for CKS, Bit 31: Disable/enable for the GFXCLK level. */
USHORT usAVFSOffset; /* AVFS Voltage offset */
} ATOM_Vega10_GFXCLK_Dependency_Record;
typedef struct _ATOM_Vega10_GFXCLK_Dependency_Record_V2 {
ULONG ulClk;
UCHAR ucVddInd;
USHORT usCKSVOffsetandDisable;
USHORT usAVFSOffset;
UCHAR ucACGEnable;
UCHAR ucReserved[3];
} ATOM_Vega10_GFXCLK_Dependency_Record_V2;
typedef struct _ATOM_Vega10_MCLK_Dependency_Record {
ULONG ulMemClk; /* Clock Frequency */
UCHAR ucVddInd; /* SOC_VDD index */
UCHAR ucVddMemInd; /* MEM_VDD - only non zero for MCLK record */
UCHAR ucVddciInd; /* VDDCI = only non zero for MCLK record */
} ATOM_Vega10_MCLK_Dependency_Record;
typedef struct _ATOM_Vega10_GFXCLK_Dependency_Table {
UCHAR ucRevId;
UCHAR ucNumEntries; /* Number of entries. */
ATOM_Vega10_GFXCLK_Dependency_Record entries[1]; /* Dynamically allocate entries. */
} ATOM_Vega10_GFXCLK_Dependency_Table;
typedef struct _ATOM_Vega10_MCLK_Dependency_Table {
UCHAR ucRevId;
UCHAR ucNumEntries; /* Number of entries. */
ATOM_Vega10_MCLK_Dependency_Record entries[1]; /* Dynamically allocate entries. */
} ATOM_Vega10_MCLK_Dependency_Table;
typedef struct _ATOM_Vega10_SOCCLK_Dependency_Table {
UCHAR ucRevId;
UCHAR ucNumEntries; /* Number of entries. */
ATOM_Vega10_CLK_Dependency_Record entries[1]; /* Dynamically allocate entries. */
} ATOM_Vega10_SOCCLK_Dependency_Table;
typedef struct _ATOM_Vega10_DCEFCLK_Dependency_Table {
UCHAR ucRevId;
UCHAR ucNumEntries; /* Number of entries. */
ATOM_Vega10_CLK_Dependency_Record entries[1]; /* Dynamically allocate entries. */
} ATOM_Vega10_DCEFCLK_Dependency_Table;
typedef struct _ATOM_Vega10_PIXCLK_Dependency_Table {
UCHAR ucRevId;
UCHAR ucNumEntries; /* Number of entries. */
ATOM_Vega10_CLK_Dependency_Record entries[1]; /* Dynamically allocate entries. */
} ATOM_Vega10_PIXCLK_Dependency_Table;
typedef struct _ATOM_Vega10_DISPCLK_Dependency_Table {
UCHAR ucRevId;
UCHAR ucNumEntries; /* Number of entries.*/
ATOM_Vega10_CLK_Dependency_Record entries[1]; /* Dynamically allocate entries. */
} ATOM_Vega10_DISPCLK_Dependency_Table;
typedef struct _ATOM_Vega10_PHYCLK_Dependency_Table {
UCHAR ucRevId;
UCHAR ucNumEntries; /* Number of entries. */
ATOM_Vega10_CLK_Dependency_Record entries[1]; /* Dynamically allocate entries. */
} ATOM_Vega10_PHYCLK_Dependency_Table;
typedef struct _ATOM_Vega10_MM_Dependency_Record {
UCHAR ucVddcInd; /* SOC_VDD voltage */
ULONG ulDClk; /* UVD D-clock */
ULONG ulVClk; /* UVD V-clock */
ULONG ulEClk; /* VCE clock */
ULONG ulPSPClk; /* PSP clock */
} ATOM_Vega10_MM_Dependency_Record;
typedef struct _ATOM_Vega10_MM_Dependency_Table {
UCHAR ucRevId;
UCHAR ucNumEntries; /* Number of entries */
ATOM_Vega10_MM_Dependency_Record entries[1]; /* Dynamically allocate entries */
} ATOM_Vega10_MM_Dependency_Table;
typedef struct _ATOM_Vega10_PCIE_Record {
ULONG ulLCLK; /* LClock */
UCHAR ucPCIEGenSpeed; /* PCIE Speed */
UCHAR ucPCIELaneWidth; /* PCIE Lane Width */
} ATOM_Vega10_PCIE_Record;
typedef struct _ATOM_Vega10_PCIE_Table {
UCHAR ucRevId;
UCHAR ucNumEntries; /* Number of entries */
ATOM_Vega10_PCIE_Record entries[1]; /* Dynamically allocate entries. */
} ATOM_Vega10_PCIE_Table;
typedef struct _ATOM_Vega10_Voltage_Lookup_Record {
USHORT usVdd; /* Base voltage */
} ATOM_Vega10_Voltage_Lookup_Record;
typedef struct _ATOM_Vega10_Voltage_Lookup_Table {
UCHAR ucRevId;
UCHAR ucNumEntries; /* Number of entries */
ATOM_Vega10_Voltage_Lookup_Record entries[1]; /* Dynamically allocate entries */
} ATOM_Vega10_Voltage_Lookup_Table;
typedef struct _ATOM_Vega10_Fan_Table {
UCHAR ucRevId; /* Change this if the table format changes or version changes so that the other fields are not the same. */
USHORT usFanOutputSensitivity; /* Sensitivity of fan reaction to temepature changes. */
USHORT usFanRPMMax; /* The default value in RPM. */
USHORT usThrottlingRPM;
USHORT usFanAcousticLimit; /* Minimum Fan Controller Frequency Acoustic Limit. */
USHORT usTargetTemperature; /* The default ideal temperature in Celcius. */
USHORT usMinimumPWMLimit; /* The minimum PWM that the advanced fan controller can set. */
USHORT usTargetGfxClk; /* The ideal Fan Controller GFXCLK Frequency Acoustic Limit. */
USHORT usFanGainEdge;
USHORT usFanGainHotspot;
USHORT usFanGainLiquid;
USHORT usFanGainVrVddc;
USHORT usFanGainVrMvdd;
USHORT usFanGainPlx;
USHORT usFanGainHbm;
UCHAR ucEnableZeroRPM;
USHORT usFanStopTemperature;
USHORT usFanStartTemperature;
} ATOM_Vega10_Fan_Table;
typedef struct _ATOM_Vega10_Fan_Table_V2 {
UCHAR ucRevId;
USHORT usFanOutputSensitivity;
USHORT usFanAcousticLimitRpm;
USHORT usThrottlingRPM;
USHORT usTargetTemperature;
USHORT usMinimumPWMLimit;
USHORT usTargetGfxClk;
USHORT usFanGainEdge;
USHORT usFanGainHotspot;
USHORT usFanGainLiquid;
USHORT usFanGainVrVddc;
USHORT usFanGainVrMvdd;
USHORT usFanGainPlx;
USHORT usFanGainHbm;
UCHAR ucEnableZeroRPM;
USHORT usFanStopTemperature;
USHORT usFanStartTemperature;
UCHAR ucFanParameters;
UCHAR ucFanMinRPM;
UCHAR ucFanMaxRPM;
} ATOM_Vega10_Fan_Table_V2;
typedef struct _ATOM_Vega10_Fan_Table_V3 {
UCHAR ucRevId;
USHORT usFanOutputSensitivity;
USHORT usFanAcousticLimitRpm;
USHORT usThrottlingRPM;
USHORT usTargetTemperature;
USHORT usMinimumPWMLimit;
USHORT usTargetGfxClk;
USHORT usFanGainEdge;
USHORT usFanGainHotspot;
USHORT usFanGainLiquid;
USHORT usFanGainVrVddc;
USHORT usFanGainVrMvdd;
USHORT usFanGainPlx;
USHORT usFanGainHbm;
UCHAR ucEnableZeroRPM;
USHORT usFanStopTemperature;
USHORT usFanStartTemperature;
UCHAR ucFanParameters;
UCHAR ucFanMinRPM;
UCHAR ucFanMaxRPM;
USHORT usMGpuThrottlingRPM;
} ATOM_Vega10_Fan_Table_V3;
typedef struct _ATOM_Vega10_Thermal_Controller {
UCHAR ucRevId;
UCHAR ucType; /* one of ATOM_VEGA10_PP_THERMALCONTROLLER_*/
UCHAR ucI2cLine; /* as interpreted by DAL I2C */
UCHAR ucI2cAddress;
UCHAR ucFanParameters; /* Fan Control Parameters. */
UCHAR ucFanMinRPM; /* Fan Minimum RPM (hundreds) -- for display purposes only.*/
UCHAR ucFanMaxRPM; /* Fan Maximum RPM (hundreds) -- for display purposes only.*/
UCHAR ucFlags; /* to be defined */
} ATOM_Vega10_Thermal_Controller;
typedef struct _ATOM_Vega10_VCE_State_Record
{
UCHAR ucVCEClockIndex; /*index into usVCEDependencyTableOffset of 'ATOM_Vega10_MM_Dependency_Table' type */
UCHAR ucFlag; /* 2 bits indicates memory p-states */
UCHAR ucSCLKIndex; /* index into ATOM_Vega10_SCLK_Dependency_Table */
UCHAR ucMCLKIndex; /* index into ATOM_Vega10_MCLK_Dependency_Table */
} ATOM_Vega10_VCE_State_Record;
typedef struct _ATOM_Vega10_VCE_State_Table
{
UCHAR ucRevId;
UCHAR ucNumEntries;
ATOM_Vega10_VCE_State_Record entries[1];
} ATOM_Vega10_VCE_State_Table;
typedef struct _ATOM_Vega10_PowerTune_Table {
UCHAR ucRevId;
USHORT usSocketPowerLimit;
USHORT usBatteryPowerLimit;
USHORT usSmallPowerLimit;
USHORT usTdcLimit;
USHORT usEdcLimit;
USHORT usSoftwareShutdownTemp;
USHORT usTemperatureLimitHotSpot;
USHORT usTemperatureLimitLiquid1;
USHORT usTemperatureLimitLiquid2;
USHORT usTemperatureLimitHBM;
USHORT usTemperatureLimitVrSoc;
USHORT usTemperatureLimitVrMem;
USHORT usTemperatureLimitPlx;
USHORT usLoadLineResistance;
UCHAR ucLiquid1_I2C_address;
UCHAR ucLiquid2_I2C_address;
UCHAR ucVr_I2C_address;
UCHAR ucPlx_I2C_address;
UCHAR ucLiquid_I2C_LineSCL;
UCHAR ucLiquid_I2C_LineSDA;
UCHAR ucVr_I2C_LineSCL;
UCHAR ucVr_I2C_LineSDA;
UCHAR ucPlx_I2C_LineSCL;
UCHAR ucPlx_I2C_LineSDA;
USHORT usTemperatureLimitTedge;
} ATOM_Vega10_PowerTune_Table;
typedef struct _ATOM_Vega10_PowerTune_Table_V2
{
UCHAR ucRevId;
USHORT usSocketPowerLimit;
USHORT usBatteryPowerLimit;
USHORT usSmallPowerLimit;
USHORT usTdcLimit;
USHORT usEdcLimit;
USHORT usSoftwareShutdownTemp;
USHORT usTemperatureLimitHotSpot;
USHORT usTemperatureLimitLiquid1;
USHORT usTemperatureLimitLiquid2;
USHORT usTemperatureLimitHBM;
USHORT usTemperatureLimitVrSoc;
USHORT usTemperatureLimitVrMem;
USHORT usTemperatureLimitPlx;
USHORT usLoadLineResistance;
UCHAR ucLiquid1_I2C_address;
UCHAR ucLiquid2_I2C_address;
UCHAR ucLiquid_I2C_Line;
UCHAR ucVr_I2C_address;
UCHAR ucVr_I2C_Line;
UCHAR ucPlx_I2C_address;
UCHAR ucPlx_I2C_Line;
USHORT usTemperatureLimitTedge;
} ATOM_Vega10_PowerTune_Table_V2;
typedef struct _ATOM_Vega10_PowerTune_Table_V3
{
UCHAR ucRevId;
USHORT usSocketPowerLimit;
USHORT usBatteryPowerLimit;
USHORT usSmallPowerLimit;
USHORT usTdcLimit;
USHORT usEdcLimit;
USHORT usSoftwareShutdownTemp;
USHORT usTemperatureLimitHotSpot;
USHORT usTemperatureLimitLiquid1;
USHORT usTemperatureLimitLiquid2;
USHORT usTemperatureLimitHBM;
USHORT usTemperatureLimitVrSoc;
USHORT usTemperatureLimitVrMem;
USHORT usTemperatureLimitPlx;
USHORT usLoadLineResistance;
UCHAR ucLiquid1_I2C_address;
UCHAR ucLiquid2_I2C_address;
UCHAR ucLiquid_I2C_Line;
UCHAR ucVr_I2C_address;
UCHAR ucVr_I2C_Line;
UCHAR ucPlx_I2C_address;
UCHAR ucPlx_I2C_Line;
USHORT usTemperatureLimitTedge;
USHORT usBoostStartTemperature;
USHORT usBoostStopTemperature;
ULONG ulBoostClock;
ULONG Reserved[2];
} ATOM_Vega10_PowerTune_Table_V3;
typedef struct _ATOM_Vega10_Hard_Limit_Record {
ULONG ulSOCCLKLimit;
ULONG ulGFXCLKLimit;
ULONG ulMCLKLimit;
USHORT usVddcLimit;
USHORT usVddciLimit;
USHORT usVddMemLimit;
} ATOM_Vega10_Hard_Limit_Record;
typedef struct _ATOM_Vega10_Hard_Limit_Table
{
UCHAR ucRevId;
UCHAR ucNumEntries;
ATOM_Vega10_Hard_Limit_Record entries[1];
} ATOM_Vega10_Hard_Limit_Table;
typedef struct _Vega10_PPTable_Generic_SubTable_Header
{
UCHAR ucRevId;
} Vega10_PPTable_Generic_SubTable_Header;
#pragma pack(pop)
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,63 @@
/*
* 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.
*
*/
#ifndef VEGA10_PROCESSPPTABLES_H
#define VEGA10_PROCESSPPTABLES_H
#include "hwmgr.h"
enum Vega10_I2CLineID {
Vega10_I2CLineID_DDC1 = 0x90,
Vega10_I2CLineID_DDC2 = 0x91,
Vega10_I2CLineID_DDC3 = 0x92,
Vega10_I2CLineID_DDC4 = 0x93,
Vega10_I2CLineID_DDC5 = 0x94,
Vega10_I2CLineID_DDC6 = 0x95,
Vega10_I2CLineID_SCLSDA = 0x96,
Vega10_I2CLineID_DDCVGA = 0x97
};
#define Vega10_I2C_DDC1DATA 0
#define Vega10_I2C_DDC1CLK 1
#define Vega10_I2C_DDC2DATA 2
#define Vega10_I2C_DDC2CLK 3
#define Vega10_I2C_DDC3DATA 4
#define Vega10_I2C_DDC3CLK 5
#define Vega10_I2C_SDA 40
#define Vega10_I2C_SCL 41
#define Vega10_I2C_DDC4DATA 65
#define Vega10_I2C_DDC4CLK 66
#define Vega10_I2C_DDC5DATA 0x48
#define Vega10_I2C_DDC5CLK 0x49
#define Vega10_I2C_DDC6DATA 0x4a
#define Vega10_I2C_DDC6CLK 0x4b
#define Vega10_I2C_DDCVGADATA 0x4c
#define Vega10_I2C_DDCVGACLK 0x4d
extern const struct pp_table_func vega10_pptable_funcs;
extern int vega10_get_number_of_powerplay_table_entries(struct pp_hwmgr *hwmgr);
extern int vega10_get_powerplay_table_entry(struct pp_hwmgr *hwmgr, uint32_t entry_index,
struct pp_power_state *power_state, int (*call_back_func)(struct pp_hwmgr *, void *,
struct pp_power_state *, void *, uint32_t));
extern int vega10_baco_set_cap(struct pp_hwmgr *hwmgr);
#endif

View File

@@ -0,0 +1,669 @@
/*
* 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 "vega10_thermal.h"
#include "vega10_hwmgr.h"
#include "vega10_smumgr.h"
#include "vega10_ppsmc.h"
#include "vega10_inc.h"
#include "soc15_common.h"
#include "pp_debug.h"
static int vega10_get_current_rpm(struct pp_hwmgr *hwmgr, uint32_t *current_rpm)
{
smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentRpm, current_rpm);
return 0;
}
int vega10_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr,
struct phm_fan_speed_info *fan_speed_info)
{
if (hwmgr->thermal_controller.fanInfo.bNoFan)
return 0;
fan_speed_info->supports_percent_read = true;
fan_speed_info->supports_percent_write = true;
fan_speed_info->min_percent = 0;
fan_speed_info->max_percent = 100;
if (PP_CAP(PHM_PlatformCaps_FanSpeedInTableIsRPM) &&
hwmgr->thermal_controller.fanInfo.
ucTachometerPulsesPerRevolution) {
fan_speed_info->supports_rpm_read = true;
fan_speed_info->supports_rpm_write = true;
fan_speed_info->min_rpm =
hwmgr->thermal_controller.fanInfo.ulMinRPM;
fan_speed_info->max_rpm =
hwmgr->thermal_controller.fanInfo.ulMaxRPM;
} else {
fan_speed_info->min_rpm = 0;
fan_speed_info->max_rpm = 0;
}
return 0;
}
int vega10_fan_ctrl_get_fan_speed_percent(struct pp_hwmgr *hwmgr,
uint32_t *speed)
{
uint32_t current_rpm;
uint32_t percent = 0;
if (hwmgr->thermal_controller.fanInfo.bNoFan)
return 0;
if (vega10_get_current_rpm(hwmgr, &current_rpm))
return -1;
if (hwmgr->thermal_controller.
advanceFanControlParameters.usMaxFanRPM != 0)
percent = current_rpm * 100 /
hwmgr->thermal_controller.
advanceFanControlParameters.usMaxFanRPM;
*speed = percent > 100 ? 100 : percent;
return 0;
}
int vega10_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t *speed)
{
struct amdgpu_device *adev = hwmgr->adev;
struct vega10_hwmgr *data = hwmgr->backend;
uint32_t tach_period;
uint32_t crystal_clock_freq;
int result = 0;
if (hwmgr->thermal_controller.fanInfo.bNoFan)
return -1;
if (data->smu_features[GNLD_FAN_CONTROL].supported) {
result = vega10_get_current_rpm(hwmgr, speed);
} else {
tach_period =
REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_TACH_STATUS),
CG_TACH_STATUS,
TACH_PERIOD);
if (tach_period == 0)
return -EINVAL;
crystal_clock_freq = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev);
*speed = 60 * crystal_clock_freq * 10000 / tach_period;
}
return result;
}
/**
* Set Fan Speed Control to static mode,
* so that the user can decide what speed to use.
* @param hwmgr the address of the powerplay hardware manager.
* mode the fan control mode, 0 default, 1 by percent, 5, by RPM
* @exception Should always succeed.
*/
int vega10_fan_ctrl_set_static_mode(struct pp_hwmgr *hwmgr, uint32_t mode)
{
struct amdgpu_device *adev = hwmgr->adev;
if (hwmgr->fan_ctrl_is_in_default_mode) {
hwmgr->fan_ctrl_default_mode =
REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL2),
CG_FDO_CTRL2, FDO_PWM_MODE);
hwmgr->tmin =
REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL2),
CG_FDO_CTRL2, TMIN);
hwmgr->fan_ctrl_is_in_default_mode = false;
}
WREG32_SOC15(THM, 0, mmCG_FDO_CTRL2,
REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL2),
CG_FDO_CTRL2, TMIN, 0));
WREG32_SOC15(THM, 0, mmCG_FDO_CTRL2,
REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL2),
CG_FDO_CTRL2, FDO_PWM_MODE, mode));
return 0;
}
/**
* Reset Fan Speed Control to default mode.
* @param hwmgr the address of the powerplay hardware manager.
* @exception Should always succeed.
*/
int vega10_fan_ctrl_set_default_mode(struct pp_hwmgr *hwmgr)
{
struct amdgpu_device *adev = hwmgr->adev;
if (!hwmgr->fan_ctrl_is_in_default_mode) {
WREG32_SOC15(THM, 0, mmCG_FDO_CTRL2,
REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL2),
CG_FDO_CTRL2, FDO_PWM_MODE,
hwmgr->fan_ctrl_default_mode));
WREG32_SOC15(THM, 0, mmCG_FDO_CTRL2,
REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL2),
CG_FDO_CTRL2, TMIN,
hwmgr->tmin << CG_FDO_CTRL2__TMIN__SHIFT));
hwmgr->fan_ctrl_is_in_default_mode = true;
}
return 0;
}
/**
* @fn vega10_enable_fan_control_feature
* @brief Enables the SMC Fan Control Feature.
*
* @param hwmgr - the address of the powerplay hardware manager.
* @return 0 on success. -1 otherwise.
*/
static int vega10_enable_fan_control_feature(struct pp_hwmgr *hwmgr)
{
struct vega10_hwmgr *data = hwmgr->backend;
if (data->smu_features[GNLD_FAN_CONTROL].supported) {
PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(
hwmgr, true,
data->smu_features[GNLD_FAN_CONTROL].
smu_feature_bitmap),
"Attempt to Enable FAN CONTROL feature Failed!",
return -1);
data->smu_features[GNLD_FAN_CONTROL].enabled = true;
}
return 0;
}
static int vega10_disable_fan_control_feature(struct pp_hwmgr *hwmgr)
{
struct vega10_hwmgr *data = hwmgr->backend;
if (data->smu_features[GNLD_FAN_CONTROL].supported) {
PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(
hwmgr, false,
data->smu_features[GNLD_FAN_CONTROL].
smu_feature_bitmap),
"Attempt to Enable FAN CONTROL feature Failed!",
return -1);
data->smu_features[GNLD_FAN_CONTROL].enabled = false;
}
return 0;
}
int vega10_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr)
{
if (hwmgr->thermal_controller.fanInfo.bNoFan)
return -1;
PP_ASSERT_WITH_CODE(!vega10_enable_fan_control_feature(hwmgr),
"Attempt to Enable SMC FAN CONTROL Feature Failed!",
return -1);
return 0;
}
int vega10_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr)
{
struct vega10_hwmgr *data = hwmgr->backend;
if (hwmgr->thermal_controller.fanInfo.bNoFan)
return -1;
if (data->smu_features[GNLD_FAN_CONTROL].supported) {
PP_ASSERT_WITH_CODE(!vega10_disable_fan_control_feature(hwmgr),
"Attempt to Disable SMC FAN CONTROL Feature Failed!",
return -1);
}
return 0;
}
/**
* Set Fan Speed in percent.
* @param hwmgr the address of the powerplay hardware manager.
* @param speed is the percentage value (0% - 100%) to be set.
* @exception Fails is the 100% setting appears to be 0.
*/
int vega10_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr,
uint32_t speed)
{
struct amdgpu_device *adev = hwmgr->adev;
uint32_t duty100;
uint32_t duty;
uint64_t tmp64;
if (hwmgr->thermal_controller.fanInfo.bNoFan)
return 0;
if (speed > 100)
speed = 100;
if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl))
vega10_fan_ctrl_stop_smc_fan_control(hwmgr);
duty100 = REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL1),
CG_FDO_CTRL1, FMAX_DUTY100);
if (duty100 == 0)
return -EINVAL;
tmp64 = (uint64_t)speed * duty100;
do_div(tmp64, 100);
duty = (uint32_t)tmp64;
WREG32_SOC15(THM, 0, mmCG_FDO_CTRL0,
REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL0),
CG_FDO_CTRL0, FDO_STATIC_DUTY, duty));
return vega10_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC);
}
/**
* Reset Fan Speed to default.
* @param hwmgr the address of the powerplay hardware manager.
* @exception Always succeeds.
*/
int vega10_fan_ctrl_reset_fan_speed_to_default(struct pp_hwmgr *hwmgr)
{
if (hwmgr->thermal_controller.fanInfo.bNoFan)
return 0;
if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl))
return vega10_fan_ctrl_start_smc_fan_control(hwmgr);
else
return vega10_fan_ctrl_set_default_mode(hwmgr);
}
/**
* Set Fan Speed in RPM.
* @param hwmgr the address of the powerplay hardware manager.
* @param speed is the percentage value (min - max) to be set.
* @exception Fails is the speed not lie between min and max.
*/
int vega10_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed)
{
struct amdgpu_device *adev = hwmgr->adev;
uint32_t tach_period;
uint32_t crystal_clock_freq;
int result = 0;
if (hwmgr->thermal_controller.fanInfo.bNoFan ||
speed == 0 ||
(speed < hwmgr->thermal_controller.fanInfo.ulMinRPM) ||
(speed > hwmgr->thermal_controller.fanInfo.ulMaxRPM))
return -1;
if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl))
result = vega10_fan_ctrl_stop_smc_fan_control(hwmgr);
if (!result) {
crystal_clock_freq = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev);
tach_period = 60 * crystal_clock_freq * 10000 / (8 * speed);
WREG32_SOC15(THM, 0, mmCG_TACH_CTRL,
REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_TACH_CTRL),
CG_TACH_CTRL, TARGET_PERIOD,
tach_period));
}
return vega10_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC_RPM);
}
/**
* Reads the remote temperature from the SIslands thermal controller.
*
* @param hwmgr The address of the hardware manager.
*/
int vega10_thermal_get_temperature(struct pp_hwmgr *hwmgr)
{
struct amdgpu_device *adev = hwmgr->adev;
int temp;
temp = RREG32_SOC15(THM, 0, mmCG_MULT_THERMAL_STATUS);
temp = (temp & CG_MULT_THERMAL_STATUS__CTF_TEMP_MASK) >>
CG_MULT_THERMAL_STATUS__CTF_TEMP__SHIFT;
temp = temp & 0x1ff;
temp *= PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
return temp;
}
/**
* Set the requested temperature range for high and low alert signals
*
* @param hwmgr The address of the hardware manager.
* @param range Temperature range to be programmed for
* high and low alert signals
* @exception PP_Result_BadInput if the input data is not valid.
*/
static int vega10_thermal_set_temperature_range(struct pp_hwmgr *hwmgr,
struct PP_TemperatureRange *range)
{
struct phm_ppt_v2_information *pp_table_info =
(struct phm_ppt_v2_information *)(hwmgr->pptable);
struct phm_tdp_table *tdp_table = pp_table_info->tdp_table;
struct amdgpu_device *adev = hwmgr->adev;
int low = VEGA10_THERMAL_MINIMUM_ALERT_TEMP;
int high = VEGA10_THERMAL_MAXIMUM_ALERT_TEMP;
uint32_t val;
/* compare them in unit celsius degree */
if (low < range->min / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)
low = range->min / PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
/*
* As a common sense, usSoftwareShutdownTemp should be bigger
* than ThotspotLimit. For any invalid usSoftwareShutdownTemp,
* we will just use the max possible setting VEGA10_THERMAL_MAXIMUM_ALERT_TEMP
* to avoid false alarms.
*/
if ((tdp_table->usSoftwareShutdownTemp >
range->hotspot_crit_max / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)) {
if (high > tdp_table->usSoftwareShutdownTemp)
high = tdp_table->usSoftwareShutdownTemp;
}
if (low > high)
return -EINVAL;
val = RREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL);
val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, MAX_IH_CREDIT, 5);
val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_IH_HW_ENA, 1);
val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, high);
val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, low);
val &= (~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK) &
(~THM_THERMAL_INT_CTRL__THERM_INTH_MASK_MASK) &
(~THM_THERMAL_INT_CTRL__THERM_INTL_MASK_MASK);
WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL, val);
return 0;
}
/**
* Programs thermal controller one-time setting registers
*
* @param hwmgr The address of the hardware manager.
*/
static int vega10_thermal_initialize(struct pp_hwmgr *hwmgr)
{
struct amdgpu_device *adev = hwmgr->adev;
if (hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution) {
WREG32_SOC15(THM, 0, mmCG_TACH_CTRL,
REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_TACH_CTRL),
CG_TACH_CTRL, EDGE_PER_REV,
hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution - 1));
}
WREG32_SOC15(THM, 0, mmCG_FDO_CTRL2,
REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL2),
CG_FDO_CTRL2, TACH_PWM_RESP_RATE, 0x28));
return 0;
}
/**
* Enable thermal alerts on the RV770 thermal controller.
*
* @param hwmgr The address of the hardware manager.
*/
static int vega10_thermal_enable_alert(struct pp_hwmgr *hwmgr)
{
struct amdgpu_device *adev = hwmgr->adev;
struct vega10_hwmgr *data = hwmgr->backend;
uint32_t val = 0;
if (data->smu_features[GNLD_FW_CTF].supported) {
if (data->smu_features[GNLD_FW_CTF].enabled)
printk("[Thermal_EnableAlert] FW CTF Already Enabled!\n");
PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr,
true,
data->smu_features[GNLD_FW_CTF].smu_feature_bitmap),
"Attempt to Enable FW CTF feature Failed!",
return -1);
data->smu_features[GNLD_FW_CTF].enabled = true;
}
val |= (1 << THM_THERMAL_INT_ENA__THERM_INTH_CLR__SHIFT);
val |= (1 << THM_THERMAL_INT_ENA__THERM_INTL_CLR__SHIFT);
val |= (1 << THM_THERMAL_INT_ENA__THERM_TRIGGER_CLR__SHIFT);
WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_ENA, val);
return 0;
}
/**
* Disable thermal alerts on the RV770 thermal controller.
* @param hwmgr The address of the hardware manager.
*/
int vega10_thermal_disable_alert(struct pp_hwmgr *hwmgr)
{
struct amdgpu_device *adev = hwmgr->adev;
struct vega10_hwmgr *data = hwmgr->backend;
if (data->smu_features[GNLD_FW_CTF].supported) {
if (!data->smu_features[GNLD_FW_CTF].enabled)
printk("[Thermal_EnableAlert] FW CTF Already disabled!\n");
PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr,
false,
data->smu_features[GNLD_FW_CTF].smu_feature_bitmap),
"Attempt to disable FW CTF feature Failed!",
return -1);
data->smu_features[GNLD_FW_CTF].enabled = false;
}
WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_ENA, 0);
return 0;
}
/**
* Uninitialize the thermal controller.
* Currently just disables alerts.
* @param hwmgr The address of the hardware manager.
*/
int vega10_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr)
{
int result = vega10_thermal_disable_alert(hwmgr);
if (!hwmgr->thermal_controller.fanInfo.bNoFan)
vega10_fan_ctrl_set_default_mode(hwmgr);
return result;
}
/**
* Set up the fan table to control the fan using the SMC.
* @param hwmgr the address of the powerplay hardware manager.
* @param pInput the pointer to input data
* @param pOutput the pointer to output data
* @param pStorage the pointer to temporary storage
* @param Result the last failure code
* @return result from set temperature range routine
*/
static int vega10_thermal_setup_fan_table(struct pp_hwmgr *hwmgr)
{
int ret;
struct vega10_hwmgr *data = hwmgr->backend;
PPTable_t *table = &(data->smc_state_table.pp_table);
if (!data->smu_features[GNLD_FAN_CONTROL].supported)
return 0;
table->FanMaximumRpm = (uint16_t)hwmgr->thermal_controller.
advanceFanControlParameters.usMaxFanRPM;
table->FanThrottlingRpm = hwmgr->thermal_controller.
advanceFanControlParameters.usFanRPMMaxLimit;
table->FanAcousticLimitRpm = (uint16_t)(hwmgr->thermal_controller.
advanceFanControlParameters.ulMinFanSCLKAcousticLimit);
table->FanTargetTemperature = hwmgr->thermal_controller.
advanceFanControlParameters.usTMax;
smum_send_msg_to_smc_with_parameter(hwmgr,
PPSMC_MSG_SetFanTemperatureTarget,
(uint32_t)table->FanTargetTemperature,
NULL);
table->FanPwmMin = hwmgr->thermal_controller.
advanceFanControlParameters.usPWMMin * 255 / 100;
table->FanTargetGfxclk = (uint16_t)(hwmgr->thermal_controller.
advanceFanControlParameters.ulTargetGfxClk);
table->FanGainEdge = hwmgr->thermal_controller.
advanceFanControlParameters.usFanGainEdge;
table->FanGainHotspot = hwmgr->thermal_controller.
advanceFanControlParameters.usFanGainHotspot;
table->FanGainLiquid = hwmgr->thermal_controller.
advanceFanControlParameters.usFanGainLiquid;
table->FanGainVrVddc = hwmgr->thermal_controller.
advanceFanControlParameters.usFanGainVrVddc;
table->FanGainVrMvdd = hwmgr->thermal_controller.
advanceFanControlParameters.usFanGainVrMvdd;
table->FanGainPlx = hwmgr->thermal_controller.
advanceFanControlParameters.usFanGainPlx;
table->FanGainHbm = hwmgr->thermal_controller.
advanceFanControlParameters.usFanGainHbm;
table->FanZeroRpmEnable = hwmgr->thermal_controller.
advanceFanControlParameters.ucEnableZeroRPM;
table->FanStopTemp = hwmgr->thermal_controller.
advanceFanControlParameters.usZeroRPMStopTemperature;
table->FanStartTemp = hwmgr->thermal_controller.
advanceFanControlParameters.usZeroRPMStartTemperature;
ret = smum_smc_table_manager(hwmgr,
(uint8_t *)(&(data->smc_state_table.pp_table)),
PPTABLE, false);
if (ret)
pr_info("Failed to update Fan Control Table in PPTable!");
return ret;
}
int vega10_enable_mgpu_fan_boost(struct pp_hwmgr *hwmgr)
{
struct vega10_hwmgr *data = hwmgr->backend;
PPTable_t *table = &(data->smc_state_table.pp_table);
int ret;
if (!data->smu_features[GNLD_FAN_CONTROL].supported)
return 0;
if (!hwmgr->thermal_controller.advanceFanControlParameters.
usMGpuThrottlingRPMLimit)
return 0;
table->FanThrottlingRpm = hwmgr->thermal_controller.
advanceFanControlParameters.usMGpuThrottlingRPMLimit;
ret = smum_smc_table_manager(hwmgr,
(uint8_t *)(&(data->smc_state_table.pp_table)),
PPTABLE, false);
if (ret) {
pr_info("Failed to update fan control table in pptable!");
return ret;
}
ret = vega10_disable_fan_control_feature(hwmgr);
if (ret) {
pr_info("Attempt to disable SMC fan control feature failed!");
return ret;
}
ret = vega10_enable_fan_control_feature(hwmgr);
if (ret)
pr_info("Attempt to enable SMC fan control feature failed!");
return ret;
}
/**
* Start the fan control on the SMC.
* @param hwmgr the address of the powerplay hardware manager.
* @param pInput the pointer to input data
* @param pOutput the pointer to output data
* @param pStorage the pointer to temporary storage
* @param Result the last failure code
* @return result from set temperature range routine
*/
static int vega10_thermal_start_smc_fan_control(struct pp_hwmgr *hwmgr)
{
/* If the fantable setup has failed we could have disabled
* PHM_PlatformCaps_MicrocodeFanControl even after
* this function was included in the table.
* Make sure that we still think controlling the fan is OK.
*/
if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl))
vega10_fan_ctrl_start_smc_fan_control(hwmgr);
return 0;
}
int vega10_start_thermal_controller(struct pp_hwmgr *hwmgr,
struct PP_TemperatureRange *range)
{
int ret = 0;
if (range == NULL)
return -EINVAL;
vega10_thermal_initialize(hwmgr);
ret = vega10_thermal_set_temperature_range(hwmgr, range);
if (ret)
return -EINVAL;
vega10_thermal_enable_alert(hwmgr);
/* We should restrict performance levels to low before we halt the SMC.
* On the other hand we are still in boot state when we do this
* so it would be pointless.
* If this assumption changes we have to revisit this table.
*/
ret = vega10_thermal_setup_fan_table(hwmgr);
if (ret)
return -EINVAL;
vega10_thermal_start_smc_fan_control(hwmgr);
return 0;
};
int vega10_thermal_ctrl_uninitialize_thermal_controller(struct pp_hwmgr *hwmgr)
{
if (!hwmgr->thermal_controller.fanInfo.bNoFan) {
vega10_fan_ctrl_set_default_mode(hwmgr);
vega10_fan_ctrl_stop_smc_fan_control(hwmgr);
}
return 0;
}

View File

@@ -0,0 +1,80 @@
/*
* Copyright 2015 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.
*
*/
#ifndef VEGA10_THERMAL_H
#define VEGA10_THERMAL_H
#include "hwmgr.h"
struct vega10_temperature {
uint16_t edge_temp;
uint16_t hot_spot_temp;
uint16_t hbm_temp;
uint16_t vr_soc_temp;
uint16_t vr_mem_temp;
uint16_t liquid1_temp;
uint16_t liquid2_temp;
uint16_t plx_temp;
};
#define VEGA10_THERMAL_HIGH_ALERT_MASK 0x1
#define VEGA10_THERMAL_LOW_ALERT_MASK 0x2
#define VEGA10_THERMAL_MINIMUM_TEMP_READING -256
#define VEGA10_THERMAL_MAXIMUM_TEMP_READING 255
#define VEGA10_THERMAL_MINIMUM_ALERT_TEMP 0
#define VEGA10_THERMAL_MAXIMUM_ALERT_TEMP 255
#define FDO_PWM_MODE_STATIC 1
#define FDO_PWM_MODE_STATIC_RPM 5
extern int vega10_thermal_get_temperature(struct pp_hwmgr *hwmgr);
extern int vega10_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr);
extern int vega10_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr,
struct phm_fan_speed_info *fan_speed_info);
extern int vega10_fan_ctrl_get_fan_speed_percent(struct pp_hwmgr *hwmgr,
uint32_t *speed);
extern int vega10_fan_ctrl_set_default_mode(struct pp_hwmgr *hwmgr);
extern int vega10_fan_ctrl_set_static_mode(struct pp_hwmgr *hwmgr,
uint32_t mode);
extern int vega10_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr,
uint32_t speed);
extern int vega10_fan_ctrl_reset_fan_speed_to_default(struct pp_hwmgr *hwmgr);
extern int vega10_thermal_ctrl_uninitialize_thermal_controller(
struct pp_hwmgr *hwmgr);
extern int vega10_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr,
uint32_t speed);
extern int vega10_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr,
uint32_t *speed);
extern int vega10_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr);
extern int vega10_thermal_disable_alert(struct pp_hwmgr *hwmgr);
extern int vega10_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr);
extern int vega10_start_thermal_controller(struct pp_hwmgr *hwmgr,
struct PP_TemperatureRange *range);
extern int vega10_enable_mgpu_fan_boost(struct pp_hwmgr *hwmgr);
#endif

View File

@@ -0,0 +1,119 @@
/*
* Copyright 2019 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 "soc15.h"
#include "soc15_hw_ip.h"
#include "vega10_ip_offset.h"
#include "soc15_common.h"
#include "vega12_inc.h"
#include "vega12_ppsmc.h"
#include "vega12_baco.h"
static const struct soc15_baco_cmd_entry pre_baco_tbl[] =
{
{ CMD_READMODIFYWRITE, NBIF_HWID, 0, mmBIF_DOORBELL_CNTL_BASE_IDX, mmBIF_DOORBELL_CNTL, BIF_DOORBELL_CNTL__DOORBELL_MONITOR_EN_MASK, BIF_DOORBELL_CNTL__DOORBELL_MONITOR_EN__SHIFT, 0, 0 },
{ CMD_WRITE, NBIF_HWID, 0, mmBIF_FB_EN_BASE_IDX, mmBIF_FB_EN, 0, 0, 0, 0 },
{ CMD_READMODIFYWRITE, NBIF_HWID, 0, mmRCC_BACO_CNTL_MISC_BASE_IDX, mmBACO_CNTL, BACO_CNTL__BACO_DSTATE_BYPASS_MASK, BACO_CNTL__BACO_DSTATE_BYPASS__SHIFT, 0, 1 },
{ CMD_READMODIFYWRITE, NBIF_HWID, 0, mmRCC_BACO_CNTL_MISC_BASE_IDX, mmBACO_CNTL, BACO_CNTL__BACO_RST_INTR_MASK_MASK, BACO_CNTL__BACO_RST_INTR_MASK__SHIFT, 0, 1 }
};
static const struct soc15_baco_cmd_entry enter_baco_tbl[] =
{
{ CMD_WAITFOR, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__SOC_DOMAIN_IDLE_MASK, THM_BACO_CNTL__SOC_DOMAIN_IDLE__SHIFT, 0xffffffff, 0x80000000 },
{ CMD_READMODIFYWRITE, NBIF_HWID, 0, mmRCC_BACO_CNTL_MISC_BASE_IDX, mmBACO_CNTL, BACO_CNTL__BACO_EN_MASK, BACO_CNTL__BACO_EN__SHIFT, 0, 1 },
{ CMD_READMODIFYWRITE, NBIF_HWID, 0, mmRCC_BACO_CNTL_MISC_BASE_IDX, mmBACO_CNTL, BACO_CNTL__BACO_BIF_LCLK_SWITCH_MASK, BACO_CNTL__BACO_BIF_LCLK_SWITCH__SHIFT, 0, 1 },
{ CMD_READMODIFYWRITE, NBIF_HWID, 0, mmRCC_BACO_CNTL_MISC_BASE_IDX, mmBACO_CNTL, BACO_CNTL__BACO_DUMMY_EN_MASK, BACO_CNTL__BACO_DUMMY_EN__SHIFT, 0, 1 },
{ CMD_READMODIFYWRITE, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_SOC_VDCI_RESET_MASK, THM_BACO_CNTL__BACO_SOC_VDCI_RESET__SHIFT, 0, 1 },
{ CMD_READMODIFYWRITE, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_SMNCLK_MUX_MASK, THM_BACO_CNTL__BACO_SMNCLK_MUX__SHIFT, 0, 1 },
{ CMD_READMODIFYWRITE, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_ISO_EN_MASK, THM_BACO_CNTL__BACO_ISO_EN__SHIFT, 0, 1 },
{ CMD_READMODIFYWRITE, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_AEB_ISO_EN_MASK, THM_BACO_CNTL__BACO_AEB_ISO_EN__SHIFT, 0, 1 },
{ CMD_READMODIFYWRITE, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_ANA_ISO_EN_MASK, THM_BACO_CNTL__BACO_ANA_ISO_EN__SHIFT, 0, 1 },
{ CMD_READMODIFYWRITE, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_SOC_REFCLK_OFF_MASK, THM_BACO_CNTL__BACO_SOC_REFCLK_OFF__SHIFT, 0, 1 },
{ CMD_READMODIFYWRITE, NBIF_HWID, 0, mmRCC_BACO_CNTL_MISC_BASE_IDX, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, BACO_CNTL__BACO_POWER_OFF__SHIFT, 0, 1 },
{ CMD_DELAY_MS, 0, 0, 0, 5, 0 },
{ CMD_READMODIFYWRITE, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_RESET_EN_MASK, THM_BACO_CNTL__BACO_RESET_EN__SHIFT, 0, 1 },
{ CMD_READMODIFYWRITE, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_PWROKRAW_CNTL_MASK, THM_BACO_CNTL__BACO_PWROKRAW_CNTL__SHIFT, 0, 0 },
{ CMD_WAITFOR, NBIF_HWID, 0, mmRCC_BACO_CNTL_MISC_BASE_IDX, mmBACO_CNTL, BACO_CNTL__BACO_MODE_MASK, BACO_CNTL__BACO_MODE__SHIFT, 0xffffffff, 0x100 }
};
static const struct soc15_baco_cmd_entry exit_baco_tbl[] =
{
{ CMD_READMODIFYWRITE, NBIF_HWID, 0, mmRCC_BACO_CNTL_MISC_BASE_IDX, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, BACO_CNTL__BACO_POWER_OFF__SHIFT, 0, 0 },
{ CMD_DELAY_MS, 0, 0, 0, 0, 0, 0, 10, 0 },
{ CMD_READMODIFYWRITE, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_SOC_REFCLK_OFF_MASK, THM_BACO_CNTL__BACO_SOC_REFCLK_OFF__SHIFT, 0, 0 },
{ CMD_READMODIFYWRITE, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_ANA_ISO_EN_MASK, THM_BACO_CNTL__BACO_ANA_ISO_EN__SHIFT, 0, 0 },
{ CMD_READMODIFYWRITE, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_AEB_ISO_EN_MASK, THM_BACO_CNTL__BACO_AEB_ISO_EN__SHIFT, 0, 0 },
{ CMD_READMODIFYWRITE, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_ISO_EN_MASK, THM_BACO_CNTL__BACO_ISO_EN__SHIFT, 0, 0 },
{ CMD_READMODIFYWRITE, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_PWROKRAW_CNTL_MASK, THM_BACO_CNTL__BACO_PWROKRAW_CNTL__SHIFT, 0, 1 },
{ CMD_READMODIFYWRITE, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_SMNCLK_MUX_MASK, THM_BACO_CNTL__BACO_SMNCLK_MUX__SHIFT, 0, 0 },
{ CMD_READMODIFYWRITE, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_SOC_VDCI_RESET_MASK, THM_BACO_CNTL__BACO_SOC_VDCI_RESET__SHIFT, 0, 0 },
{ CMD_READMODIFYWRITE, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_EXIT_MASK, THM_BACO_CNTL__BACO_EXIT__SHIFT, 0, 1 },
{ CMD_READMODIFYWRITE, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_RESET_EN_MASK, THM_BACO_CNTL__BACO_RESET_EN__SHIFT, 0, 0 },
{ CMD_WAITFOR, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_EXIT_MASK, 0, 0xffffffff, 0 },
{ CMD_READMODIFYWRITE, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_SB_AXI_FENCE_MASK, THM_BACO_CNTL__BACO_SB_AXI_FENCE__SHIFT, 0, 0 },
{ CMD_READMODIFYWRITE, NBIF_HWID, 0, mmRCC_BACO_CNTL_MISC_BASE_IDX, mmBACO_CNTL, BACO_CNTL__BACO_DUMMY_EN_MASK, BACO_CNTL__BACO_DUMMY_EN__SHIFT, 0, 0 },
{ CMD_READMODIFYWRITE, NBIF_HWID, 0, mmRCC_BACO_CNTL_MISC_BASE_IDX, mmBACO_CNTL, BACO_CNTL__BACO_BIF_LCLK_SWITCH_MASK, BACO_CNTL__BACO_BIF_LCLK_SWITCH__SHIFT, 0, 0 },
{ CMD_READMODIFYWRITE, NBIF_HWID, 0, mmRCC_BACO_CNTL_MISC_BASE_IDX, mmBACO_CNTL, BACO_CNTL__BACO_EN_MASK, BACO_CNTL__BACO_EN__SHIFT, 0, 0 },
{ CMD_WAITFOR, NBIF_HWID, 0, mmRCC_BACO_CNTL_MISC_BASE_IDX, mmBACO_CNTL, BACO_CNTL__BACO_MODE_MASK, 0, 0xffffffff, 0 }
};
static const struct soc15_baco_cmd_entry clean_baco_tbl[] =
{
{ CMD_WRITE, NBIF_HWID, 0, mmBIOS_SCRATCH_6_BASE_IDX, mmBIOS_SCRATCH_6, 0, 0, 0, 0 },
{ CMD_WRITE, NBIF_HWID, 0, mmBIOS_SCRATCH_7_BASE_IDX, mmBIOS_SCRATCH_7, 0, 0, 0, 0 }
};
int vega12_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state)
{
enum BACO_STATE cur_state;
smu9_baco_get_state(hwmgr, &cur_state);
if (cur_state == state)
/* aisc already in the target state */
return 0;
if (state == BACO_STATE_IN) {
if (soc15_baco_program_registers(hwmgr, pre_baco_tbl,
ARRAY_SIZE(pre_baco_tbl))) {
if (smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_EnterBaco, 0, NULL))
return -EINVAL;
if (soc15_baco_program_registers(hwmgr, enter_baco_tbl,
ARRAY_SIZE(enter_baco_tbl)))
return 0;
}
} else if (state == BACO_STATE_OUT) {
/* HW requires at least 20ms between regulator off and on */
msleep(20);
/* Execute Hardware BACO exit sequence */
if (soc15_baco_program_registers(hwmgr, exit_baco_tbl,
ARRAY_SIZE(exit_baco_tbl))) {
if (soc15_baco_program_registers(hwmgr, clean_baco_tbl,
ARRAY_SIZE(clean_baco_tbl)))
return 0;
}
}
return -EINVAL;
}

View File

@@ -0,0 +1,29 @@
/*
* Copyright 2019 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.
*
*/
#ifndef __VEGA12_BACO_H__
#define __VEGA12_BACO_H__
#include "smu9_baco.h"
extern int vega12_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,458 @@
/*
* Copyright 2017 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.
*
*/
#ifndef _VEGA12_HWMGR_H_
#define _VEGA12_HWMGR_H_
#include "hwmgr.h"
#include "vega12/smu9_driver_if.h"
#include "ppatomfwctrl.h"
#define VEGA12_MAX_HARDWARE_POWERLEVELS 2
#define WaterMarksExist 1
#define WaterMarksLoaded 2
#define VG12_PSUEDO_NUM_GFXCLK_DPM_LEVELS 16
#define VG12_PSUEDO_NUM_SOCCLK_DPM_LEVELS 8
#define VG12_PSUEDO_NUM_DCEFCLK_DPM_LEVELS 8
#define VG12_PSUEDO_NUM_UCLK_DPM_LEVELS 4
enum
{
GNLD_DPM_PREFETCHER = 0,
GNLD_DPM_GFXCLK,
GNLD_DPM_UCLK,
GNLD_DPM_SOCCLK,
GNLD_DPM_UVD,
GNLD_DPM_VCE,
GNLD_ULV,
GNLD_DPM_MP0CLK,
GNLD_DPM_LINK,
GNLD_DPM_DCEFCLK,
GNLD_DS_GFXCLK,
GNLD_DS_SOCCLK,
GNLD_DS_LCLK,
GNLD_PPT,
GNLD_TDC,
GNLD_THERMAL,
GNLD_GFX_PER_CU_CG,
GNLD_RM,
GNLD_DS_DCEFCLK,
GNLD_ACDC,
GNLD_VR0HOT,
GNLD_VR1HOT,
GNLD_FW_CTF,
GNLD_LED_DISPLAY,
GNLD_FAN_CONTROL,
GNLD_DIDT,
GNLD_GFXOFF,
GNLD_CG,
GNLD_ACG,
GNLD_FEATURES_MAX
};
#define GNLD_DPM_MAX (GNLD_DPM_DCEFCLK + 1)
#define SMC_DPM_FEATURES 0x30F
struct smu_features {
bool supported;
bool enabled;
bool allowed;
uint32_t smu_feature_id;
uint64_t smu_feature_bitmap;
};
struct vega12_dpm_level {
bool enabled;
uint32_t value;
uint32_t param1;
};
#define VEGA12_MAX_DEEPSLEEP_DIVIDER_ID 5
#define MAX_REGULAR_DPM_NUMBER 16
#define MAX_PCIE_CONF 2
#define VEGA12_MINIMUM_ENGINE_CLOCK 2500
struct vega12_dpm_state {
uint32_t soft_min_level;
uint32_t soft_max_level;
uint32_t hard_min_level;
uint32_t hard_max_level;
};
struct vega12_single_dpm_table {
uint32_t count;
struct vega12_dpm_state dpm_state;
struct vega12_dpm_level dpm_levels[MAX_REGULAR_DPM_NUMBER];
};
struct vega12_odn_dpm_control {
uint32_t count;
uint32_t entries[MAX_REGULAR_DPM_NUMBER];
};
struct vega12_pcie_table {
uint16_t count;
uint8_t pcie_gen[MAX_PCIE_CONF];
uint8_t pcie_lane[MAX_PCIE_CONF];
uint32_t lclk[MAX_PCIE_CONF];
};
struct vega12_dpm_table {
struct vega12_single_dpm_table soc_table;
struct vega12_single_dpm_table gfx_table;
struct vega12_single_dpm_table mem_table;
struct vega12_single_dpm_table eclk_table;
struct vega12_single_dpm_table vclk_table;
struct vega12_single_dpm_table dclk_table;
struct vega12_single_dpm_table dcef_table;
struct vega12_single_dpm_table pixel_table;
struct vega12_single_dpm_table display_table;
struct vega12_single_dpm_table phy_table;
struct vega12_pcie_table pcie_table;
};
#define VEGA12_MAX_LEAKAGE_COUNT 8
struct vega12_leakage_voltage {
uint16_t count;
uint16_t leakage_id[VEGA12_MAX_LEAKAGE_COUNT];
uint16_t actual_voltage[VEGA12_MAX_LEAKAGE_COUNT];
};
struct vega12_display_timing {
uint32_t min_clock_in_sr;
uint32_t num_existing_displays;
};
struct vega12_dpmlevel_enable_mask {
uint32_t uvd_dpm_enable_mask;
uint32_t vce_dpm_enable_mask;
uint32_t samu_dpm_enable_mask;
uint32_t sclk_dpm_enable_mask;
uint32_t mclk_dpm_enable_mask;
};
struct vega12_vbios_boot_state {
bool bsoc_vddc_lock;
uint8_t uc_cooling_id;
uint16_t vddc;
uint16_t vddci;
uint16_t mvddc;
uint16_t vdd_gfx;
uint32_t gfx_clock;
uint32_t mem_clock;
uint32_t soc_clock;
uint32_t dcef_clock;
uint32_t eclock;
uint32_t dclock;
uint32_t vclock;
};
#define DPMTABLE_OD_UPDATE_SCLK 0x00000001
#define DPMTABLE_OD_UPDATE_MCLK 0x00000002
#define DPMTABLE_UPDATE_SCLK 0x00000004
#define DPMTABLE_UPDATE_MCLK 0x00000008
#define DPMTABLE_OD_UPDATE_VDDC 0x00000010
struct vega12_smc_state_table {
uint32_t soc_boot_level;
uint32_t gfx_boot_level;
uint32_t dcef_boot_level;
uint32_t mem_boot_level;
uint32_t uvd_boot_level;
uint32_t vce_boot_level;
uint32_t gfx_max_level;
uint32_t mem_max_level;
uint8_t vr_hot_gpio;
uint8_t ac_dc_gpio;
uint8_t therm_out_gpio;
uint8_t therm_out_polarity;
uint8_t therm_out_mode;
PPTable_t pp_table;
Watermarks_t water_marks_table;
AvfsDebugTable_t avfs_debug_table;
AvfsFuseOverride_t avfs_fuse_override_table;
SmuMetrics_t smu_metrics;
DriverSmuConfig_t driver_smu_config;
DpmActivityMonitorCoeffInt_t dpm_activity_monitor_coeffint;
OverDriveTable_t overdrive_table;
};
struct vega12_mclk_latency_entries {
uint32_t frequency;
uint32_t latency;
};
struct vega12_mclk_latency_table {
uint32_t count;
struct vega12_mclk_latency_entries entries[MAX_REGULAR_DPM_NUMBER];
};
struct vega12_registry_data {
uint64_t disallowed_features;
uint8_t ac_dc_switch_gpio_support;
uint8_t acg_loop_support;
uint8_t clock_stretcher_support;
uint8_t db_ramping_support;
uint8_t didt_mode;
uint8_t didt_support;
uint8_t edc_didt_support;
uint8_t force_dpm_high;
uint8_t fuzzy_fan_control_support;
uint8_t mclk_dpm_key_disabled;
uint8_t od_state_in_dc_support;
uint8_t pcie_lane_override;
uint8_t pcie_speed_override;
uint32_t pcie_clock_override;
uint8_t pcie_dpm_key_disabled;
uint8_t dcefclk_dpm_key_disabled;
uint8_t prefetcher_dpm_key_disabled;
uint8_t quick_transition_support;
uint8_t regulator_hot_gpio_support;
uint8_t master_deep_sleep_support;
uint8_t gfx_clk_deep_sleep_support;
uint8_t sclk_deep_sleep_support;
uint8_t lclk_deep_sleep_support;
uint8_t dce_fclk_deep_sleep_support;
uint8_t sclk_dpm_key_disabled;
uint8_t sclk_throttle_low_notification;
uint8_t skip_baco_hardware;
uint8_t socclk_dpm_key_disabled;
uint8_t sq_ramping_support;
uint8_t tcp_ramping_support;
uint8_t td_ramping_support;
uint8_t dbr_ramping_support;
uint8_t gc_didt_support;
uint8_t psm_didt_support;
uint8_t thermal_support;
uint8_t fw_ctf_enabled;
uint8_t led_dpm_enabled;
uint8_t fan_control_support;
uint8_t ulv_support;
uint8_t odn_feature_enable;
uint8_t disable_water_mark;
uint8_t disable_workload_policy;
uint32_t force_workload_policy_mask;
uint8_t disable_3d_fs_detection;
uint8_t disable_pp_tuning;
uint8_t disable_xlpp_tuning;
uint32_t perf_ui_tuning_profile_turbo;
uint32_t perf_ui_tuning_profile_powerSave;
uint32_t perf_ui_tuning_profile_xl;
uint16_t zrpm_stop_temp;
uint16_t zrpm_start_temp;
uint32_t stable_pstate_sclk_dpm_percentage;
uint8_t fps_support;
uint8_t vr0hot;
uint8_t vr1hot;
uint8_t disable_auto_wattman;
uint32_t auto_wattman_debug;
uint32_t auto_wattman_sample_period;
uint8_t auto_wattman_threshold;
uint8_t log_avfs_param;
uint8_t enable_enginess;
uint8_t custom_fan_support;
uint8_t disable_pcc_limit_control;
};
struct vega12_odn_clock_voltage_dependency_table {
uint32_t count;
struct phm_ppt_v1_clock_voltage_dependency_record
entries[MAX_REGULAR_DPM_NUMBER];
};
struct vega12_odn_dpm_table {
struct vega12_odn_dpm_control control_gfxclk_state;
struct vega12_odn_dpm_control control_memclk_state;
struct phm_odn_clock_levels odn_core_clock_dpm_levels;
struct phm_odn_clock_levels odn_memory_clock_dpm_levels;
struct vega12_odn_clock_voltage_dependency_table vdd_dependency_on_sclk;
struct vega12_odn_clock_voltage_dependency_table vdd_dependency_on_mclk;
struct vega12_odn_clock_voltage_dependency_table vdd_dependency_on_socclk;
uint32_t odn_mclk_min_limit;
};
struct vega12_odn_fan_table {
uint32_t target_fan_speed;
uint32_t target_temperature;
uint32_t min_performance_clock;
uint32_t min_fan_limit;
bool force_fan_pwm;
};
struct vega12_clock_range {
uint32_t ACMax;
uint32_t ACMin;
uint32_t DCMax;
};
struct vega12_hwmgr {
struct vega12_dpm_table dpm_table;
struct vega12_dpm_table golden_dpm_table;
struct vega12_registry_data registry_data;
struct vega12_vbios_boot_state vbios_boot_state;
struct vega12_mclk_latency_table mclk_latency_table;
struct vega12_leakage_voltage vddc_leakage;
uint32_t vddc_control;
struct pp_atomfwctrl_voltage_table vddc_voltage_table;
uint32_t mvdd_control;
struct pp_atomfwctrl_voltage_table mvdd_voltage_table;
uint32_t vddci_control;
struct pp_atomfwctrl_voltage_table vddci_voltage_table;
uint32_t active_auto_throttle_sources;
uint32_t water_marks_bitmap;
struct vega12_odn_dpm_table odn_dpm_table;
struct vega12_odn_fan_table odn_fan_table;
/* ---- General data ---- */
uint8_t need_update_dpm_table;
bool cac_enabled;
bool battery_state;
bool is_tlu_enabled;
bool avfs_exist;
uint32_t low_sclk_interrupt_threshold;
uint32_t total_active_cus;
struct vega12_display_timing display_timing;
/* ---- Vega12 Dyn Register Settings ---- */
uint32_t debug_settings;
uint32_t lowest_uclk_reserved_for_ulv;
uint32_t gfxclk_average_alpha;
uint32_t socclk_average_alpha;
uint32_t uclk_average_alpha;
uint32_t gfx_activity_average_alpha;
uint32_t display_voltage_mode;
uint32_t dcef_clk_quad_eqn_a;
uint32_t dcef_clk_quad_eqn_b;
uint32_t dcef_clk_quad_eqn_c;
uint32_t disp_clk_quad_eqn_a;
uint32_t disp_clk_quad_eqn_b;
uint32_t disp_clk_quad_eqn_c;
uint32_t pixel_clk_quad_eqn_a;
uint32_t pixel_clk_quad_eqn_b;
uint32_t pixel_clk_quad_eqn_c;
uint32_t phy_clk_quad_eqn_a;
uint32_t phy_clk_quad_eqn_b;
uint32_t phy_clk_quad_eqn_c;
/* ---- Thermal Temperature Setting ---- */
struct vega12_dpmlevel_enable_mask dpm_level_enable_mask;
/* ---- Power Gating States ---- */
bool uvd_power_gated;
bool vce_power_gated;
bool samu_power_gated;
bool need_long_memory_training;
/* Internal settings to apply the application power optimization parameters */
bool apply_optimized_settings;
uint32_t disable_dpm_mask;
/* ---- Overdrive next setting ---- */
uint32_t apply_overdrive_next_settings_mask;
/* ---- Workload Mask ---- */
uint32_t workload_mask;
/* ---- SMU9 ---- */
uint32_t smu_version;
struct smu_features smu_features[GNLD_FEATURES_MAX];
struct vega12_smc_state_table smc_state_table;
struct vega12_clock_range clk_range[PPCLK_COUNT];
/* ---- Gfxoff ---- */
bool gfxoff_controlled_by_driver;
unsigned long metrics_time;
SmuMetrics_t metrics_table;
struct gpu_metrics_v1_0 gpu_metrics_table;
};
#define VEGA12_DPM2_NEAR_TDP_DEC 10
#define VEGA12_DPM2_ABOVE_SAFE_INC 5
#define VEGA12_DPM2_BELOW_SAFE_INC 20
#define VEGA12_DPM2_LTA_WINDOW_SIZE 7
#define VEGA12_DPM2_LTS_TRUNCATE 0
#define VEGA12_DPM2_TDP_SAFE_LIMIT_PERCENT 80
#define VEGA12_DPM2_MAXPS_PERCENT_M 90
#define VEGA12_DPM2_MAXPS_PERCENT_H 90
#define VEGA12_DPM2_PWREFFICIENCYRATIO_MARGIN 50
#define VEGA12_DPM2_SQ_RAMP_MAX_POWER 0x3FFF
#define VEGA12_DPM2_SQ_RAMP_MIN_POWER 0x12
#define VEGA12_DPM2_SQ_RAMP_MAX_POWER_DELTA 0x15
#define VEGA12_DPM2_SQ_RAMP_SHORT_TERM_INTERVAL_SIZE 0x1E
#define VEGA12_DPM2_SQ_RAMP_LONG_TERM_INTERVAL_RATIO 0xF
#define VEGA12_VOLTAGE_CONTROL_NONE 0x0
#define VEGA12_VOLTAGE_CONTROL_BY_GPIO 0x1
#define VEGA12_VOLTAGE_CONTROL_BY_SVID2 0x2
#define VEGA12_VOLTAGE_CONTROL_MERGED 0x3
/* To convert to Q8.8 format for firmware */
#define VEGA12_Q88_FORMAT_CONVERSION_UNIT 256
#define VEGA12_UNUSED_GPIO_PIN 0x7F
#define VEGA12_THERM_OUT_MODE_DISABLE 0x0
#define VEGA12_THERM_OUT_MODE_THERM_ONLY 0x1
#define VEGA12_THERM_OUT_MODE_THERM_VRHOT 0x2
#define PPVEGA12_VEGA12DISPLAYVOLTAGEMODE_DFLT 0xffffffff
#define PPREGKEY_VEGA12QUADRATICEQUATION_DFLT 0xffffffff
#define PPVEGA12_VEGA12GFXCLKAVERAGEALPHA_DFLT 25 /* 10% * 255 = 25 */
#define PPVEGA12_VEGA12SOCCLKAVERAGEALPHA_DFLT 25 /* 10% * 255 = 25 */
#define PPVEGA12_VEGA12UCLKCLKAVERAGEALPHA_DFLT 25 /* 10% * 255 = 25 */
#define PPVEGA12_VEGA12GFXACTIVITYAVERAGEALPHA_DFLT 25 /* 10% * 255 = 25 */
#define PPVEGA12_VEGA12LOWESTUCLKRESERVEDFORULV_DFLT 0xffffffff
#define PPVEGA12_VEGA12DISPLAYVOLTAGEMODE_DFLT 0xffffffff
#define PPREGKEY_VEGA12QUADRATICEQUATION_DFLT 0xffffffff
#define VEGA12_UMD_PSTATE_GFXCLK_LEVEL 0x3
#define VEGA12_UMD_PSTATE_SOCCLK_LEVEL 0x3
#define VEGA12_UMD_PSTATE_MCLK_LEVEL 0x2
#define VEGA12_UMD_PSTATE_UVDCLK_LEVEL 0x3
#define VEGA12_UMD_PSTATE_VCEMCLK_LEVEL 0x3
int vega12_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable);
#endif /* _VEGA12_HWMGR_H_ */

View File

@@ -0,0 +1,40 @@
/*
* Copyright 2017 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.
*
*/
#ifndef VEGA12_INC_H
#define VEGA12_INC_H
#include "asic_reg/thm/thm_9_0_default.h"
#include "asic_reg/thm/thm_9_0_offset.h"
#include "asic_reg/thm/thm_9_0_sh_mask.h"
#include "asic_reg/mp/mp_9_0_offset.h"
#include "asic_reg/mp/mp_9_0_sh_mask.h"
#include "asic_reg/gc/gc_9_2_1_offset.h"
#include "asic_reg/gc/gc_9_2_1_sh_mask.h"
#include "asic_reg/nbio/nbio_6_1_offset.h"
#include "asic_reg/nbio/nbio_6_1_sh_mask.h"
#endif

View File

@@ -0,0 +1,109 @@
/*
* Copyright 2017 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.
*
*/
#ifndef _VEGA12_PPTABLE_H_
#define _VEGA12_PPTABLE_H_
#pragma pack(push, 1)
#define ATOM_VEGA12_PP_THERMALCONTROLLER_NONE 0
#define ATOM_VEGA12_PP_THERMALCONTROLLER_VEGA12 25
#define ATOM_VEGA12_PP_PLATFORM_CAP_POWERPLAY 0x1
#define ATOM_VEGA12_PP_PLATFORM_CAP_SBIOSPOWERSOURCE 0x2
#define ATOM_VEGA12_PP_PLATFORM_CAP_HARDWAREDC 0x4
#define ATOM_VEGA12_PP_PLATFORM_CAP_BACO 0x8
#define ATOM_VEGA12_PP_PLATFORM_CAP_BAMACO 0x10
#define ATOM_VEGA12_PP_PLATFORM_CAP_ENABLESHADOWPSTATE 0x20
#define ATOM_VEGA12_TABLE_REVISION_VEGA12 9
enum ATOM_VEGA12_ODSETTING_ID {
ATOM_VEGA12_ODSETTING_GFXCLKFMAX = 0,
ATOM_VEGA12_ODSETTING_GFXCLKFMIN,
ATOM_VEGA12_ODSETTING_VDDGFXCURVEFREQ_P1,
ATOM_VEGA12_ODSETTING_VDDGFXCURVEVOLTAGEOFFSET_P1,
ATOM_VEGA12_ODSETTING_VDDGFXCURVEFREQ_P2,
ATOM_VEGA12_ODSETTING_VDDGFXCURVEVOLTAGEOFFSET_P2,
ATOM_VEGA12_ODSETTING_VDDGFXCURVEFREQ_P3,
ATOM_VEGA12_ODSETTING_VDDGFXCURVEVOLTAGEOFFSET_P3,
ATOM_VEGA12_ODSETTING_UCLKFMAX,
ATOM_VEGA12_ODSETTING_POWERPERCENTAGE,
ATOM_VEGA12_ODSETTING_FANRPMMIN,
ATOM_VEGA12_ODSETTING_FANRPMACOUSTICLIMIT,
ATOM_VEGA12_ODSETTING_FANTARGETTEMPERATURE,
ATOM_VEGA12_ODSETTING_OPERATINGTEMPMAX,
ATOM_VEGA12_ODSETTING_COUNT,
};
typedef enum ATOM_VEGA12_ODSETTING_ID ATOM_VEGA12_ODSETTING_ID;
enum ATOM_VEGA12_PPCLOCK_ID {
ATOM_VEGA12_PPCLOCK_GFXCLK = 0,
ATOM_VEGA12_PPCLOCK_VCLK,
ATOM_VEGA12_PPCLOCK_DCLK,
ATOM_VEGA12_PPCLOCK_ECLK,
ATOM_VEGA12_PPCLOCK_SOCCLK,
ATOM_VEGA12_PPCLOCK_UCLK,
ATOM_VEGA12_PPCLOCK_DCEFCLK,
ATOM_VEGA12_PPCLOCK_DISPCLK,
ATOM_VEGA12_PPCLOCK_PIXCLK,
ATOM_VEGA12_PPCLOCK_PHYCLK,
ATOM_VEGA12_PPCLOCK_COUNT,
};
typedef enum ATOM_VEGA12_PPCLOCK_ID ATOM_VEGA12_PPCLOCK_ID;
typedef struct _ATOM_VEGA12_POWERPLAYTABLE
{
struct atom_common_table_header sHeader;
UCHAR ucTableRevision;
USHORT usTableSize;
ULONG ulGoldenPPID;
ULONG ulGoldenRevision;
USHORT usFormatID;
ULONG ulPlatformCaps;
UCHAR ucThermalControllerType;
USHORT usSmallPowerLimit1;
USHORT usSmallPowerLimit2;
USHORT usBoostPowerLimit;
USHORT usODTurboPowerLimit;
USHORT usODPowerSavePowerLimit;
USHORT usSoftwareShutdownTemp;
ULONG PowerSavingClockMax [ATOM_VEGA12_PPCLOCK_COUNT];
ULONG PowerSavingClockMin [ATOM_VEGA12_PPCLOCK_COUNT];
ULONG ODSettingsMax [ATOM_VEGA12_ODSETTING_COUNT];
ULONG ODSettingsMin [ATOM_VEGA12_ODSETTING_COUNT];
USHORT usReserve[5];
PPTable_t smcPPTable;
} ATOM_Vega12_POWERPLAYTABLE;
#pragma pack(pop)
#endif

View File

@@ -0,0 +1,402 @@
/*
* Copyright 2017 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/module.h>
#include <linux/slab.h>
#include <linux/fb.h>
#include "vega12/smu9_driver_if.h"
#include "vega12_processpptables.h"
#include "ppatomfwctrl.h"
#include "atomfirmware.h"
#include "pp_debug.h"
#include "cgs_common.h"
#include "vega12_pptable.h"
static void set_hw_cap(struct pp_hwmgr *hwmgr, bool enable,
enum phm_platform_caps cap)
{
if (enable)
phm_cap_set(hwmgr->platform_descriptor.platformCaps, cap);
else
phm_cap_unset(hwmgr->platform_descriptor.platformCaps, cap);
}
static const void *get_powerplay_table(struct pp_hwmgr *hwmgr)
{
int index = GetIndexIntoMasterDataTable(powerplayinfo);
u16 size;
u8 frev, crev;
const void *table_address = hwmgr->soft_pp_table;
if (!table_address) {
table_address = (ATOM_Vega12_POWERPLAYTABLE *)
smu_atom_get_data_table(hwmgr->adev, index,
&size, &frev, &crev);
hwmgr->soft_pp_table = table_address; /*Cache the result in RAM.*/
hwmgr->soft_pp_table_size = size;
}
return table_address;
}
static int check_powerplay_tables(
struct pp_hwmgr *hwmgr,
const ATOM_Vega12_POWERPLAYTABLE *powerplay_table)
{
PP_ASSERT_WITH_CODE((powerplay_table->sHeader.format_revision >=
ATOM_VEGA12_TABLE_REVISION_VEGA12),
"Unsupported PPTable format!", return -1);
PP_ASSERT_WITH_CODE(powerplay_table->sHeader.structuresize > 0,
"Invalid PowerPlay Table!", return -1);
return 0;
}
static int set_platform_caps(struct pp_hwmgr *hwmgr, uint32_t powerplay_caps)
{
set_hw_cap(
hwmgr,
0 != (powerplay_caps & ATOM_VEGA12_PP_PLATFORM_CAP_POWERPLAY),
PHM_PlatformCaps_PowerPlaySupport);
set_hw_cap(
hwmgr,
0 != (powerplay_caps & ATOM_VEGA12_PP_PLATFORM_CAP_SBIOSPOWERSOURCE),
PHM_PlatformCaps_BiosPowerSourceControl);
set_hw_cap(
hwmgr,
0 != (powerplay_caps & ATOM_VEGA12_PP_PLATFORM_CAP_BACO),
PHM_PlatformCaps_BACO);
set_hw_cap(
hwmgr,
0 != (powerplay_caps & ATOM_VEGA12_PP_PLATFORM_CAP_BAMACO),
PHM_PlatformCaps_BAMACO);
return 0;
}
static int append_vbios_pptable(struct pp_hwmgr *hwmgr, PPTable_t *ppsmc_pptable)
{
struct pp_atomfwctrl_smc_dpm_parameters smc_dpm_table;
PP_ASSERT_WITH_CODE(
pp_atomfwctrl_get_smc_dpm_information(hwmgr, &smc_dpm_table) == 0,
"[appendVbiosPPTable] Failed to retrieve Smc Dpm Table from VBIOS!",
return -1);
ppsmc_pptable->Liquid1_I2C_address = smc_dpm_table.liquid1_i2c_address;
ppsmc_pptable->Liquid2_I2C_address = smc_dpm_table.liquid2_i2c_address;
ppsmc_pptable->Vr_I2C_address = smc_dpm_table.vr_i2c_address;
ppsmc_pptable->Plx_I2C_address = smc_dpm_table.plx_i2c_address;
ppsmc_pptable->Liquid_I2C_LineSCL = smc_dpm_table.liquid_i2c_linescl;
ppsmc_pptable->Liquid_I2C_LineSDA = smc_dpm_table.liquid_i2c_linesda;
ppsmc_pptable->Vr_I2C_LineSCL = smc_dpm_table.vr_i2c_linescl;
ppsmc_pptable->Vr_I2C_LineSDA = smc_dpm_table.vr_i2c_linesda;
ppsmc_pptable->Plx_I2C_LineSCL = smc_dpm_table.plx_i2c_linescl;
ppsmc_pptable->Plx_I2C_LineSDA = smc_dpm_table.plx_i2c_linesda;
ppsmc_pptable->VrSensorPresent = smc_dpm_table.vrsensorpresent;
ppsmc_pptable->LiquidSensorPresent = smc_dpm_table.liquidsensorpresent;
ppsmc_pptable->MaxVoltageStepGfx = smc_dpm_table.maxvoltagestepgfx;
ppsmc_pptable->MaxVoltageStepSoc = smc_dpm_table.maxvoltagestepsoc;
ppsmc_pptable->VddGfxVrMapping = smc_dpm_table.vddgfxvrmapping;
ppsmc_pptable->VddSocVrMapping = smc_dpm_table.vddsocvrmapping;
ppsmc_pptable->VddMem0VrMapping = smc_dpm_table.vddmem0vrmapping;
ppsmc_pptable->VddMem1VrMapping = smc_dpm_table.vddmem1vrmapping;
ppsmc_pptable->GfxUlvPhaseSheddingMask = smc_dpm_table.gfxulvphasesheddingmask;
ppsmc_pptable->SocUlvPhaseSheddingMask = smc_dpm_table.soculvphasesheddingmask;
ppsmc_pptable->GfxMaxCurrent = smc_dpm_table.gfxmaxcurrent;
ppsmc_pptable->GfxOffset = smc_dpm_table.gfxoffset;
ppsmc_pptable->Padding_TelemetryGfx = smc_dpm_table.padding_telemetrygfx;
ppsmc_pptable->SocMaxCurrent = smc_dpm_table.socmaxcurrent;
ppsmc_pptable->SocOffset = smc_dpm_table.socoffset;
ppsmc_pptable->Padding_TelemetrySoc = smc_dpm_table.padding_telemetrysoc;
ppsmc_pptable->Mem0MaxCurrent = smc_dpm_table.mem0maxcurrent;
ppsmc_pptable->Mem0Offset = smc_dpm_table.mem0offset;
ppsmc_pptable->Padding_TelemetryMem0 = smc_dpm_table.padding_telemetrymem0;
ppsmc_pptable->Mem1MaxCurrent = smc_dpm_table.mem1maxcurrent;
ppsmc_pptable->Mem1Offset = smc_dpm_table.mem1offset;
ppsmc_pptable->Padding_TelemetryMem1 = smc_dpm_table.padding_telemetrymem1;
ppsmc_pptable->AcDcGpio = smc_dpm_table.acdcgpio;
ppsmc_pptable->AcDcPolarity = smc_dpm_table.acdcpolarity;
ppsmc_pptable->VR0HotGpio = smc_dpm_table.vr0hotgpio;
ppsmc_pptable->VR0HotPolarity = smc_dpm_table.vr0hotpolarity;
ppsmc_pptable->VR1HotGpio = smc_dpm_table.vr1hotgpio;
ppsmc_pptable->VR1HotPolarity = smc_dpm_table.vr1hotpolarity;
ppsmc_pptable->Padding1 = smc_dpm_table.padding1;
ppsmc_pptable->Padding2 = smc_dpm_table.padding2;
ppsmc_pptable->LedPin0 = smc_dpm_table.ledpin0;
ppsmc_pptable->LedPin1 = smc_dpm_table.ledpin1;
ppsmc_pptable->LedPin2 = smc_dpm_table.ledpin2;
ppsmc_pptable->PllGfxclkSpreadEnabled = smc_dpm_table.pllgfxclkspreadenabled;
ppsmc_pptable->PllGfxclkSpreadPercent = smc_dpm_table.pllgfxclkspreadpercent;
ppsmc_pptable->PllGfxclkSpreadFreq = smc_dpm_table.pllgfxclkspreadfreq;
ppsmc_pptable->UclkSpreadEnabled = 0;
ppsmc_pptable->UclkSpreadPercent = smc_dpm_table.uclkspreadpercent;
ppsmc_pptable->UclkSpreadFreq = smc_dpm_table.uclkspreadfreq;
ppsmc_pptable->SocclkSpreadEnabled = 0;
ppsmc_pptable->SocclkSpreadPercent = smc_dpm_table.socclkspreadpercent;
ppsmc_pptable->SocclkSpreadFreq = smc_dpm_table.socclkspreadfreq;
ppsmc_pptable->AcgGfxclkSpreadEnabled = smc_dpm_table.acggfxclkspreadenabled;
ppsmc_pptable->AcgGfxclkSpreadPercent = smc_dpm_table.acggfxclkspreadpercent;
ppsmc_pptable->AcgGfxclkSpreadFreq = smc_dpm_table.acggfxclkspreadfreq;
ppsmc_pptable->Vr2_I2C_address = smc_dpm_table.Vr2_I2C_address;
ppsmc_pptable->Vr2_I2C_address = smc_dpm_table.Vr2_I2C_address;
return 0;
}
#define VEGA12_ENGINECLOCK_HARDMAX 198000
static int init_powerplay_table_information(
struct pp_hwmgr *hwmgr,
const ATOM_Vega12_POWERPLAYTABLE *powerplay_table)
{
struct phm_ppt_v3_information *pptable_information =
(struct phm_ppt_v3_information *)hwmgr->pptable;
uint32_t disable_power_control = 0;
int result;
hwmgr->thermal_controller.ucType = powerplay_table->ucThermalControllerType;
pptable_information->uc_thermal_controller_type = powerplay_table->ucThermalControllerType;
set_hw_cap(hwmgr,
ATOM_VEGA12_PP_THERMALCONTROLLER_NONE != hwmgr->thermal_controller.ucType,
PHM_PlatformCaps_ThermalController);
phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl);
if (le32_to_cpu(powerplay_table->ODSettingsMax[ATOM_VEGA12_ODSETTING_GFXCLKFMAX]) > VEGA12_ENGINECLOCK_HARDMAX)
hwmgr->platform_descriptor.overdriveLimit.engineClock = VEGA12_ENGINECLOCK_HARDMAX;
else
hwmgr->platform_descriptor.overdriveLimit.engineClock =
le32_to_cpu(powerplay_table->ODSettingsMax[ATOM_VEGA12_ODSETTING_GFXCLKFMAX]);
hwmgr->platform_descriptor.overdriveLimit.memoryClock =
le32_to_cpu(powerplay_table->ODSettingsMax[ATOM_VEGA12_ODSETTING_UCLKFMAX]);
phm_copy_overdrive_settings_limits_array(hwmgr,
&pptable_information->od_settings_max,
powerplay_table->ODSettingsMax,
ATOM_VEGA12_ODSETTING_COUNT);
phm_copy_overdrive_settings_limits_array(hwmgr,
&pptable_information->od_settings_min,
powerplay_table->ODSettingsMin,
ATOM_VEGA12_ODSETTING_COUNT);
/* hwmgr->platformDescriptor.minOverdriveVDDC = 0;
hwmgr->platformDescriptor.maxOverdriveVDDC = 0;
hwmgr->platformDescriptor.overdriveVDDCStep = 0; */
if (hwmgr->platform_descriptor.overdriveLimit.engineClock > 0
&& hwmgr->platform_descriptor.overdriveLimit.memoryClock > 0)
phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_ACOverdriveSupport);
pptable_information->us_small_power_limit1 = le16_to_cpu(powerplay_table->usSmallPowerLimit1);
pptable_information->us_small_power_limit2 = le16_to_cpu(powerplay_table->usSmallPowerLimit2);
pptable_information->us_boost_power_limit = le16_to_cpu(powerplay_table->usBoostPowerLimit);
pptable_information->us_od_turbo_power_limit = le16_to_cpu(powerplay_table->usODTurboPowerLimit);
pptable_information->us_od_powersave_power_limit = le16_to_cpu(powerplay_table->usODPowerSavePowerLimit);
pptable_information->us_software_shutdown_temp = le16_to_cpu(powerplay_table->usSoftwareShutdownTemp);
hwmgr->platform_descriptor.TDPODLimit = le32_to_cpu(powerplay_table->ODSettingsMax[ATOM_VEGA12_ODSETTING_POWERPERCENTAGE]);
disable_power_control = 0;
if (!disable_power_control) {
/* enable TDP overdrive (PowerControl) feature as well if supported */
if (hwmgr->platform_descriptor.TDPODLimit)
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_PowerControl);
}
phm_copy_clock_limits_array(hwmgr, &pptable_information->power_saving_clock_max, powerplay_table->PowerSavingClockMax, ATOM_VEGA12_PPCLOCK_COUNT);
phm_copy_clock_limits_array(hwmgr, &pptable_information->power_saving_clock_min, powerplay_table->PowerSavingClockMin, ATOM_VEGA12_PPCLOCK_COUNT);
pptable_information->smc_pptable = kmalloc(sizeof(PPTable_t), GFP_KERNEL);
if (pptable_information->smc_pptable == NULL)
return -ENOMEM;
memcpy(pptable_information->smc_pptable, &(powerplay_table->smcPPTable), sizeof(PPTable_t));
result = append_vbios_pptable(hwmgr, (pptable_information->smc_pptable));
return result;
}
static int vega12_pp_tables_initialize(struct pp_hwmgr *hwmgr)
{
int result = 0;
const ATOM_Vega12_POWERPLAYTABLE *powerplay_table;
hwmgr->pptable = kzalloc(sizeof(struct phm_ppt_v3_information), GFP_KERNEL);
PP_ASSERT_WITH_CODE((hwmgr->pptable != NULL),
"Failed to allocate hwmgr->pptable!", return -ENOMEM);
powerplay_table = get_powerplay_table(hwmgr);
PP_ASSERT_WITH_CODE((powerplay_table != NULL),
"Missing PowerPlay Table!", return -1);
result = check_powerplay_tables(hwmgr, powerplay_table);
PP_ASSERT_WITH_CODE((result == 0),
"check_powerplay_tables failed", return result);
result = set_platform_caps(hwmgr,
le32_to_cpu(powerplay_table->ulPlatformCaps));
PP_ASSERT_WITH_CODE((result == 0),
"set_platform_caps failed", return result);
result = init_powerplay_table_information(hwmgr, powerplay_table);
PP_ASSERT_WITH_CODE((result == 0),
"init_powerplay_table_information failed", return result);
return result;
}
static int vega12_pp_tables_uninitialize(struct pp_hwmgr *hwmgr)
{
struct phm_ppt_v3_information *pp_table_info =
(struct phm_ppt_v3_information *)(hwmgr->pptable);
kfree(pp_table_info->power_saving_clock_max);
pp_table_info->power_saving_clock_max = NULL;
kfree(pp_table_info->power_saving_clock_min);
pp_table_info->power_saving_clock_min = NULL;
kfree(pp_table_info->od_settings_max);
pp_table_info->od_settings_max = NULL;
kfree(pp_table_info->od_settings_min);
pp_table_info->od_settings_min = NULL;
kfree(pp_table_info->smc_pptable);
pp_table_info->smc_pptable = NULL;
kfree(hwmgr->pptable);
hwmgr->pptable = NULL;
return 0;
}
const struct pp_table_func vega12_pptable_funcs = {
.pptable_init = vega12_pp_tables_initialize,
.pptable_fini = vega12_pp_tables_uninitialize,
};
#if 0
static uint32_t make_classification_flags(struct pp_hwmgr *hwmgr,
uint16_t classification, uint16_t classification2)
{
uint32_t result = 0;
if (classification & ATOM_PPLIB_CLASSIFICATION_BOOT)
result |= PP_StateClassificationFlag_Boot;
if (classification & ATOM_PPLIB_CLASSIFICATION_THERMAL)
result |= PP_StateClassificationFlag_Thermal;
if (classification & ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE)
result |= PP_StateClassificationFlag_LimitedPowerSource;
if (classification & ATOM_PPLIB_CLASSIFICATION_REST)
result |= PP_StateClassificationFlag_Rest;
if (classification & ATOM_PPLIB_CLASSIFICATION_FORCED)
result |= PP_StateClassificationFlag_Forced;
if (classification & ATOM_PPLIB_CLASSIFICATION_ACPI)
result |= PP_StateClassificationFlag_ACPI;
if (classification2 & ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2)
result |= PP_StateClassificationFlag_LimitedPowerSource_2;
return result;
}
int vega12_get_powerplay_table_entry(struct pp_hwmgr *hwmgr,
uint32_t entry_index, struct pp_power_state *power_state,
int (*call_back_func)(struct pp_hwmgr *, void *,
struct pp_power_state *, void *, uint32_t))
{
int result = 0;
const ATOM_Vega12_State_Array *state_arrays;
const ATOM_Vega12_State *state_entry;
const ATOM_Vega12_POWERPLAYTABLE *pp_table =
get_powerplay_table(hwmgr);
PP_ASSERT_WITH_CODE(pp_table, "Missing PowerPlay Table!",
return -1;);
power_state->classification.bios_index = entry_index;
if (pp_table->sHeader.format_revision >=
ATOM_Vega12_TABLE_REVISION_VEGA12) {
state_arrays = (ATOM_Vega12_State_Array *)
(((unsigned long)pp_table) +
le16_to_cpu(pp_table->usStateArrayOffset));
PP_ASSERT_WITH_CODE(pp_table->usStateArrayOffset > 0,
"Invalid PowerPlay Table State Array Offset.",
return -1);
PP_ASSERT_WITH_CODE(state_arrays->ucNumEntries > 0,
"Invalid PowerPlay Table State Array.",
return -1);
PP_ASSERT_WITH_CODE((entry_index <= state_arrays->ucNumEntries),
"Invalid PowerPlay Table State Array Entry.",
return -1);
state_entry = &(state_arrays->states[entry_index]);
result = call_back_func(hwmgr, (void *)state_entry, power_state,
(void *)pp_table,
make_classification_flags(hwmgr,
le16_to_cpu(state_entry->usClassification),
le16_to_cpu(state_entry->usClassification2)));
}
if (!result && (power_state->classification.flags &
PP_StateClassificationFlag_Boot))
result = hwmgr->hwmgr_func->patch_boot_state(hwmgr, &(power_state->hardware));
return result;
}
#endif

View File

@@ -0,0 +1,58 @@
/*
* Copyright 2017 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.
*
*/
#ifndef VEGA12_PROCESSPPTABLES_H
#define VEGA12_PROCESSPPTABLES_H
#include "hwmgr.h"
enum Vega12_I2CLineID {
Vega12_I2CLineID_DDC1 = 0x90,
Vega12_I2CLineID_DDC2 = 0x91,
Vega12_I2CLineID_DDC3 = 0x92,
Vega12_I2CLineID_DDC4 = 0x93,
Vega12_I2CLineID_DDC5 = 0x94,
Vega12_I2CLineID_DDC6 = 0x95,
Vega12_I2CLineID_SCLSDA = 0x96,
Vega12_I2CLineID_DDCVGA = 0x97
};
#define Vega12_I2C_DDC1DATA 0
#define Vega12_I2C_DDC1CLK 1
#define Vega12_I2C_DDC2DATA 2
#define Vega12_I2C_DDC2CLK 3
#define Vega12_I2C_DDC3DATA 4
#define Vega12_I2C_DDC3CLK 5
#define Vega12_I2C_SDA 40
#define Vega12_I2C_SCL 41
#define Vega12_I2C_DDC4DATA 65
#define Vega12_I2C_DDC4CLK 66
#define Vega12_I2C_DDC5DATA 0x48
#define Vega12_I2C_DDC5CLK 0x49
#define Vega12_I2C_DDC6DATA 0x4a
#define Vega12_I2C_DDC6CLK 0x4b
#define Vega12_I2C_DDCVGADATA 0x4c
#define Vega12_I2C_DDCVGACLK 0x4d
extern const struct pp_table_func vega12_pptable_funcs;
#endif

View File

@@ -0,0 +1,317 @@
/*
* Copyright 2017 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 "vega12_thermal.h"
#include "vega12_hwmgr.h"
#include "vega12_smumgr.h"
#include "vega12_ppsmc.h"
#include "vega12_inc.h"
#include "soc15_common.h"
#include "pp_debug.h"
static int vega12_get_current_rpm(struct pp_hwmgr *hwmgr, uint32_t *current_rpm)
{
PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc(hwmgr,
PPSMC_MSG_GetCurrentRpm,
current_rpm),
"Attempt to get current RPM from SMC Failed!",
return -EINVAL);
return 0;
}
int vega12_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr,
struct phm_fan_speed_info *fan_speed_info)
{
memset(fan_speed_info, 0, sizeof(*fan_speed_info));
fan_speed_info->supports_percent_read = false;
fan_speed_info->supports_percent_write = false;
fan_speed_info->supports_rpm_read = true;
fan_speed_info->supports_rpm_write = true;
return 0;
}
int vega12_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t *speed)
{
*speed = 0;
return vega12_get_current_rpm(hwmgr, speed);
}
/**
* @fn vega12_enable_fan_control_feature
* @brief Enables the SMC Fan Control Feature.
*
* @param hwmgr - the address of the powerplay hardware manager.
* @return 0 on success. -1 otherwise.
*/
static int vega12_enable_fan_control_feature(struct pp_hwmgr *hwmgr)
{
#if 0
struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
if (data->smu_features[GNLD_FAN_CONTROL].supported) {
PP_ASSERT_WITH_CODE(!vega12_enable_smc_features(
hwmgr, true,
data->smu_features[GNLD_FAN_CONTROL].
smu_feature_bitmap),
"Attempt to Enable FAN CONTROL feature Failed!",
return -1);
data->smu_features[GNLD_FAN_CONTROL].enabled = true;
}
#endif
return 0;
}
static int vega12_disable_fan_control_feature(struct pp_hwmgr *hwmgr)
{
#if 0
struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
if (data->smu_features[GNLD_FAN_CONTROL].supported) {
PP_ASSERT_WITH_CODE(!vega12_enable_smc_features(
hwmgr, false,
data->smu_features[GNLD_FAN_CONTROL].
smu_feature_bitmap),
"Attempt to Enable FAN CONTROL feature Failed!",
return -1);
data->smu_features[GNLD_FAN_CONTROL].enabled = false;
}
#endif
return 0;
}
int vega12_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr)
{
struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
if (data->smu_features[GNLD_FAN_CONTROL].supported)
PP_ASSERT_WITH_CODE(
!vega12_enable_fan_control_feature(hwmgr),
"Attempt to Enable SMC FAN CONTROL Feature Failed!",
return -1);
return 0;
}
int vega12_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr)
{
struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
if (data->smu_features[GNLD_FAN_CONTROL].supported)
PP_ASSERT_WITH_CODE(!vega12_disable_fan_control_feature(hwmgr),
"Attempt to Disable SMC FAN CONTROL Feature Failed!",
return -1);
return 0;
}
/**
* Reset Fan Speed to default.
* @param hwmgr the address of the powerplay hardware manager.
* @exception Always succeeds.
*/
int vega12_fan_ctrl_reset_fan_speed_to_default(struct pp_hwmgr *hwmgr)
{
return vega12_fan_ctrl_start_smc_fan_control(hwmgr);
}
/**
* Reads the remote temperature from the SIslands thermal controller.
*
* @param hwmgr The address of the hardware manager.
*/
int vega12_thermal_get_temperature(struct pp_hwmgr *hwmgr)
{
struct amdgpu_device *adev = hwmgr->adev;
int temp = 0;
temp = RREG32_SOC15(THM, 0, mmCG_MULT_THERMAL_STATUS);
temp = (temp & CG_MULT_THERMAL_STATUS__CTF_TEMP_MASK) >>
CG_MULT_THERMAL_STATUS__CTF_TEMP__SHIFT;
temp = temp & 0x1ff;
temp *= PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
return temp;
}
/**
* Set the requested temperature range for high and low alert signals
*
* @param hwmgr The address of the hardware manager.
* @param range Temperature range to be programmed for
* high and low alert signals
* @exception PP_Result_BadInput if the input data is not valid.
*/
static int vega12_thermal_set_temperature_range(struct pp_hwmgr *hwmgr,
struct PP_TemperatureRange *range)
{
struct phm_ppt_v3_information *pptable_information =
(struct phm_ppt_v3_information *)hwmgr->pptable;
struct amdgpu_device *adev = hwmgr->adev;
int low = VEGA12_THERMAL_MINIMUM_ALERT_TEMP;
int high = VEGA12_THERMAL_MAXIMUM_ALERT_TEMP;
uint32_t val;
/* compare them in unit celsius degree */
if (low < range->min / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)
low = range->min / PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
if (high > pptable_information->us_software_shutdown_temp)
high = pptable_information->us_software_shutdown_temp;
if (low > high)
return -EINVAL;
val = RREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL);
val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, MAX_IH_CREDIT, 5);
val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_IH_HW_ENA, 1);
val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, high);
val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, low);
val = val & (~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK);
WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL, val);
return 0;
}
/**
* Enable thermal alerts on the RV770 thermal controller.
*
* @param hwmgr The address of the hardware manager.
*/
static int vega12_thermal_enable_alert(struct pp_hwmgr *hwmgr)
{
struct amdgpu_device *adev = hwmgr->adev;
uint32_t val = 0;
val |= (1 << THM_THERMAL_INT_ENA__THERM_INTH_CLR__SHIFT);
val |= (1 << THM_THERMAL_INT_ENA__THERM_INTL_CLR__SHIFT);
val |= (1 << THM_THERMAL_INT_ENA__THERM_TRIGGER_CLR__SHIFT);
WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_ENA, val);
return 0;
}
/**
* Disable thermal alerts on the RV770 thermal controller.
* @param hwmgr The address of the hardware manager.
*/
int vega12_thermal_disable_alert(struct pp_hwmgr *hwmgr)
{
struct amdgpu_device *adev = hwmgr->adev;
WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_ENA, 0);
return 0;
}
/**
* Uninitialize the thermal controller.
* Currently just disables alerts.
* @param hwmgr The address of the hardware manager.
*/
int vega12_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr)
{
int result = vega12_thermal_disable_alert(hwmgr);
return result;
}
/**
* Set up the fan table to control the fan using the SMC.
* @param hwmgr the address of the powerplay hardware manager.
* @param pInput the pointer to input data
* @param pOutput the pointer to output data
* @param pStorage the pointer to temporary storage
* @param Result the last failure code
* @return result from set temperature range routine
*/
static int vega12_thermal_setup_fan_table(struct pp_hwmgr *hwmgr)
{
int ret;
struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend);
PPTable_t *table = &(data->smc_state_table.pp_table);
ret = smum_send_msg_to_smc_with_parameter(hwmgr,
PPSMC_MSG_SetFanTemperatureTarget,
(uint32_t)table->FanTargetTemperature,
NULL);
return ret;
}
/**
* Start the fan control on the SMC.
* @param hwmgr the address of the powerplay hardware manager.
* @param pInput the pointer to input data
* @param pOutput the pointer to output data
* @param pStorage the pointer to temporary storage
* @param Result the last failure code
* @return result from set temperature range routine
*/
static int vega12_thermal_start_smc_fan_control(struct pp_hwmgr *hwmgr)
{
/* If the fantable setup has failed we could have disabled
* PHM_PlatformCaps_MicrocodeFanControl even after
* this function was included in the table.
* Make sure that we still think controlling the fan is OK.
*/
if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl))
vega12_fan_ctrl_start_smc_fan_control(hwmgr);
return 0;
}
int vega12_start_thermal_controller(struct pp_hwmgr *hwmgr,
struct PP_TemperatureRange *range)
{
int ret = 0;
if (range == NULL)
return -EINVAL;
ret = vega12_thermal_set_temperature_range(hwmgr, range);
if (ret)
return -EINVAL;
vega12_thermal_enable_alert(hwmgr);
/* We should restrict performance levels to low before we halt the SMC.
* On the other hand we are still in boot state when we do this
* so it would be pointless.
* If this assumption changes we have to revisit this table.
*/
ret = vega12_thermal_setup_fan_table(hwmgr);
if (ret)
return -EINVAL;
vega12_thermal_start_smc_fan_control(hwmgr);
return 0;
};

View File

@@ -0,0 +1,66 @@
/*
* Copyright 2017 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.
*
*/
#ifndef VEGA12_THERMAL_H
#define VEGA12_THERMAL_H
#include "hwmgr.h"
struct vega12_temperature {
uint16_t edge_temp;
uint16_t hot_spot_temp;
uint16_t hbm_temp;
uint16_t vr_soc_temp;
uint16_t vr_mem_temp;
uint16_t liquid1_temp;
uint16_t liquid2_temp;
uint16_t plx_temp;
};
#define VEGA12_THERMAL_HIGH_ALERT_MASK 0x1
#define VEGA12_THERMAL_LOW_ALERT_MASK 0x2
#define VEGA12_THERMAL_MINIMUM_TEMP_READING -256
#define VEGA12_THERMAL_MAXIMUM_TEMP_READING 255
#define VEGA12_THERMAL_MINIMUM_ALERT_TEMP 0
#define VEGA12_THERMAL_MAXIMUM_ALERT_TEMP 255
#define FDO_PWM_MODE_STATIC 1
#define FDO_PWM_MODE_STATIC_RPM 5
extern int vega12_thermal_get_temperature(struct pp_hwmgr *hwmgr);
extern int vega12_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr);
extern int vega12_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr,
struct phm_fan_speed_info *fan_speed_info);
extern int vega12_fan_ctrl_reset_fan_speed_to_default(struct pp_hwmgr *hwmgr);
extern int vega12_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr,
uint32_t *speed);
extern int vega12_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr);
extern int vega12_thermal_disable_alert(struct pp_hwmgr *hwmgr);
extern int vega12_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr);
extern int vega12_start_thermal_controller(struct pp_hwmgr *hwmgr,
struct PP_TemperatureRange *range);
#endif

View File

@@ -0,0 +1,122 @@
/*
* Copyright 2018 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 "soc15.h"
#include "soc15_hw_ip.h"
#include "soc15_common.h"
#include "vega20_inc.h"
#include "vega20_ppsmc.h"
#include "vega20_baco.h"
#include "vega20_smumgr.h"
#include "amdgpu_ras.h"
static const struct soc15_baco_cmd_entry clean_baco_tbl[] =
{
{CMD_WRITE, SOC15_REG_ENTRY(NBIF, 0, mmBIOS_SCRATCH_6), 0, 0, 0, 0},
{CMD_WRITE, SOC15_REG_ENTRY(NBIF, 0, mmBIOS_SCRATCH_7), 0, 0, 0, 0},
};
int vega20_baco_get_capability(struct pp_hwmgr *hwmgr, bool *cap)
{
struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev);
uint32_t reg;
*cap = false;
if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_BACO))
return 0;
if (((RREG32(0x17569) & 0x20000000) >> 29) == 0x1) {
reg = RREG32_SOC15(NBIF, 0, mmRCC_BIF_STRAP0);
if (reg & RCC_BIF_STRAP0__STRAP_PX_CAPABLE_MASK)
*cap = true;
}
return 0;
}
int vega20_baco_get_state(struct pp_hwmgr *hwmgr, enum BACO_STATE *state)
{
struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev);
uint32_t reg;
reg = RREG32_SOC15(NBIF, 0, mmBACO_CNTL);
if (reg & BACO_CNTL__BACO_MODE_MASK)
/* gfx has already entered BACO state */
*state = BACO_STATE_IN;
else
*state = BACO_STATE_OUT;
return 0;
}
int vega20_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state)
{
struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev);
struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
enum BACO_STATE cur_state;
uint32_t data;
vega20_baco_get_state(hwmgr, &cur_state);
if (cur_state == state)
/* aisc already in the target state */
return 0;
if (state == BACO_STATE_IN) {
if (!ras || !ras->supported) {
data = RREG32_SOC15(THM, 0, mmTHM_BACO_CNTL);
data |= 0x80000000;
WREG32_SOC15(THM, 0, mmTHM_BACO_CNTL, data);
if(smum_send_msg_to_smc_with_parameter(hwmgr,
PPSMC_MSG_EnterBaco, 0, NULL))
return -EINVAL;
} else {
if(smum_send_msg_to_smc_with_parameter(hwmgr,
PPSMC_MSG_EnterBaco, 1, NULL))
return -EINVAL;
}
} else if (state == BACO_STATE_OUT) {
if (smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ExitBaco, NULL))
return -EINVAL;
if (!soc15_baco_program_registers(hwmgr, clean_baco_tbl,
ARRAY_SIZE(clean_baco_tbl)))
return -EINVAL;
}
return 0;
}
int vega20_baco_apply_vdci_flush_workaround(struct pp_hwmgr *hwmgr)
{
int ret = 0;
ret = vega20_set_pptable_driver_address(hwmgr);
if (ret)
return ret;
return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_BacoWorkAroundFlushVDCI, NULL);
}

View File

@@ -0,0 +1,33 @@
/*
* Copyright 2018 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.
*
*/
#ifndef __VEGA20_BACO_H__
#define __VEGA20_BACO_H__
#include "hwmgr.h"
#include "common_baco.h"
extern int vega20_baco_get_capability(struct pp_hwmgr *hwmgr, bool *cap);
extern int vega20_baco_get_state(struct pp_hwmgr *hwmgr, enum BACO_STATE *state);
extern int vega20_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state);
extern int vega20_baco_apply_vdci_flush_workaround(struct pp_hwmgr *hwmgr);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,590 @@
/*
* Copyright 2018 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.
*
*/
#ifndef _VEGA20_HWMGR_H_
#define _VEGA20_HWMGR_H_
#include "hwmgr.h"
#include "smu11_driver_if.h"
#include "ppatomfwctrl.h"
#define VEGA20_MAX_HARDWARE_POWERLEVELS 2
#define WaterMarksExist 1
#define WaterMarksLoaded 2
#define VG20_PSUEDO_NUM_GFXCLK_DPM_LEVELS 8
#define VG20_PSUEDO_NUM_SOCCLK_DPM_LEVELS 8
#define VG20_PSUEDO_NUM_DCEFCLK_DPM_LEVELS 8
#define VG20_PSUEDO_NUM_UCLK_DPM_LEVELS 4
//OverDriver8 macro defs
#define AVFS_CURVE 0
#define OD8_HOTCURVE_TEMPERATURE 85
#define VG20_CLOCK_MAX_DEFAULT 0xFFFF
typedef uint32_t PP_Clock;
enum {
GNLD_DPM_PREFETCHER = 0,
GNLD_DPM_GFXCLK,
GNLD_DPM_UCLK,
GNLD_DPM_SOCCLK,
GNLD_DPM_UVD,
GNLD_DPM_VCE,
GNLD_ULV,
GNLD_DPM_MP0CLK,
GNLD_DPM_LINK,
GNLD_DPM_DCEFCLK,
GNLD_DS_GFXCLK,
GNLD_DS_SOCCLK,
GNLD_DS_LCLK,
GNLD_PPT,
GNLD_TDC,
GNLD_THERMAL,
GNLD_GFX_PER_CU_CG,
GNLD_RM,
GNLD_DS_DCEFCLK,
GNLD_ACDC,
GNLD_VR0HOT,
GNLD_VR1HOT,
GNLD_FW_CTF,
GNLD_LED_DISPLAY,
GNLD_FAN_CONTROL,
GNLD_DIDT,
GNLD_GFXOFF,
GNLD_CG,
GNLD_DPM_FCLK,
GNLD_DS_FCLK,
GNLD_DS_MP1CLK,
GNLD_DS_MP0CLK,
GNLD_XGMI,
GNLD_ECC,
GNLD_FEATURES_MAX
};
#define GNLD_DPM_MAX (GNLD_DPM_DCEFCLK + 1)
#define SMC_DPM_FEATURES 0x30F
struct smu_features {
bool supported;
bool enabled;
bool allowed;
uint32_t smu_feature_id;
uint64_t smu_feature_bitmap;
};
struct vega20_performance_level {
uint32_t soc_clock;
uint32_t gfx_clock;
uint32_t mem_clock;
};
struct vega20_bacos {
uint32_t baco_flags;
/* struct vega20_performance_level performance_level; */
};
struct vega20_uvd_clocks {
uint32_t vclk;
uint32_t dclk;
};
struct vega20_vce_clocks {
uint32_t evclk;
uint32_t ecclk;
};
struct vega20_power_state {
uint32_t magic;
struct vega20_uvd_clocks uvd_clks;
struct vega20_vce_clocks vce_clks;
uint16_t performance_level_count;
bool dc_compatible;
uint32_t sclk_threshold;
struct vega20_performance_level performance_levels[VEGA20_MAX_HARDWARE_POWERLEVELS];
};
struct vega20_dpm_level {
bool enabled;
uint32_t value;
uint32_t param1;
};
#define VEGA20_MAX_DEEPSLEEP_DIVIDER_ID 5
#define MAX_REGULAR_DPM_NUMBER 16
#define MAX_PCIE_CONF 2
#define VEGA20_MINIMUM_ENGINE_CLOCK 2500
struct vega20_max_sustainable_clocks {
PP_Clock display_clock;
PP_Clock phy_clock;
PP_Clock pixel_clock;
PP_Clock uclock;
PP_Clock dcef_clock;
PP_Clock soc_clock;
};
struct vega20_dpm_state {
uint32_t soft_min_level;
uint32_t soft_max_level;
uint32_t hard_min_level;
uint32_t hard_max_level;
};
struct vega20_single_dpm_table {
uint32_t count;
struct vega20_dpm_state dpm_state;
struct vega20_dpm_level dpm_levels[MAX_REGULAR_DPM_NUMBER];
};
struct vega20_odn_dpm_control {
uint32_t count;
uint32_t entries[MAX_REGULAR_DPM_NUMBER];
};
struct vega20_pcie_table {
uint16_t count;
uint8_t pcie_gen[MAX_PCIE_CONF];
uint8_t pcie_lane[MAX_PCIE_CONF];
uint32_t lclk[MAX_PCIE_CONF];
};
struct vega20_dpm_table {
struct vega20_single_dpm_table soc_table;
struct vega20_single_dpm_table gfx_table;
struct vega20_single_dpm_table mem_table;
struct vega20_single_dpm_table eclk_table;
struct vega20_single_dpm_table vclk_table;
struct vega20_single_dpm_table dclk_table;
struct vega20_single_dpm_table dcef_table;
struct vega20_single_dpm_table pixel_table;
struct vega20_single_dpm_table display_table;
struct vega20_single_dpm_table phy_table;
struct vega20_single_dpm_table fclk_table;
struct vega20_pcie_table pcie_table;
};
#define VEGA20_MAX_LEAKAGE_COUNT 8
struct vega20_leakage_voltage {
uint16_t count;
uint16_t leakage_id[VEGA20_MAX_LEAKAGE_COUNT];
uint16_t actual_voltage[VEGA20_MAX_LEAKAGE_COUNT];
};
struct vega20_display_timing {
uint32_t min_clock_in_sr;
uint32_t num_existing_displays;
};
struct vega20_dpmlevel_enable_mask {
uint32_t uvd_dpm_enable_mask;
uint32_t vce_dpm_enable_mask;
uint32_t samu_dpm_enable_mask;
uint32_t sclk_dpm_enable_mask;
uint32_t mclk_dpm_enable_mask;
};
struct vega20_vbios_boot_state {
uint8_t uc_cooling_id;
uint16_t vddc;
uint16_t vddci;
uint16_t mvddc;
uint16_t vdd_gfx;
uint32_t gfx_clock;
uint32_t mem_clock;
uint32_t soc_clock;
uint32_t dcef_clock;
uint32_t eclock;
uint32_t dclock;
uint32_t vclock;
uint32_t fclock;
};
#define DPMTABLE_OD_UPDATE_SCLK 0x00000001
#define DPMTABLE_OD_UPDATE_MCLK 0x00000002
#define DPMTABLE_UPDATE_SCLK 0x00000004
#define DPMTABLE_UPDATE_MCLK 0x00000008
#define DPMTABLE_OD_UPDATE_VDDC 0x00000010
#define DPMTABLE_OD_UPDATE_SCLK_MASK 0x00000020
#define DPMTABLE_OD_UPDATE_MCLK_MASK 0x00000040
// To determine if sclk and mclk are in overdrive state
#define SCLK_MASK_OVERDRIVE_ENABLED 0x00000008
#define MCLK_MASK_OVERDRIVE_ENABLED 0x00000010
#define SOCCLK_OVERDRIVE_ENABLED 0x00000020
struct vega20_smc_state_table {
uint32_t soc_boot_level;
uint32_t gfx_boot_level;
uint32_t dcef_boot_level;
uint32_t mem_boot_level;
uint32_t uvd_boot_level;
uint32_t vce_boot_level;
uint32_t gfx_max_level;
uint32_t mem_max_level;
uint8_t vr_hot_gpio;
uint8_t ac_dc_gpio;
uint8_t therm_out_gpio;
uint8_t therm_out_polarity;
uint8_t therm_out_mode;
PPTable_t pp_table;
Watermarks_t water_marks_table;
AvfsDebugTable_t avfs_debug_table;
AvfsFuseOverride_t avfs_fuse_override_table;
SmuMetrics_t smu_metrics;
DriverSmuConfig_t driver_smu_config;
DpmActivityMonitorCoeffInt_t dpm_activity_monitor_coeffint;
OverDriveTable_t overdrive_table;
};
struct vega20_mclk_latency_entries {
uint32_t frequency;
uint32_t latency;
};
struct vega20_mclk_latency_table {
uint32_t count;
struct vega20_mclk_latency_entries entries[MAX_REGULAR_DPM_NUMBER];
};
struct vega20_registry_data {
uint64_t disallowed_features;
uint8_t ac_dc_switch_gpio_support;
uint8_t acg_loop_support;
uint8_t clock_stretcher_support;
uint8_t db_ramping_support;
uint8_t didt_mode;
uint8_t didt_support;
uint8_t edc_didt_support;
uint8_t force_dpm_high;
uint8_t fuzzy_fan_control_support;
uint8_t mclk_dpm_key_disabled;
uint8_t od_state_in_dc_support;
uint8_t pcie_lane_override;
uint8_t pcie_speed_override;
uint32_t pcie_clock_override;
uint8_t pcie_dpm_key_disabled;
uint8_t dcefclk_dpm_key_disabled;
uint8_t prefetcher_dpm_key_disabled;
uint8_t quick_transition_support;
uint8_t regulator_hot_gpio_support;
uint8_t master_deep_sleep_support;
uint8_t gfx_clk_deep_sleep_support;
uint8_t sclk_deep_sleep_support;
uint8_t lclk_deep_sleep_support;
uint8_t dce_fclk_deep_sleep_support;
uint8_t sclk_dpm_key_disabled;
uint8_t sclk_throttle_low_notification;
uint8_t skip_baco_hardware;
uint8_t socclk_dpm_key_disabled;
uint8_t sq_ramping_support;
uint8_t tcp_ramping_support;
uint8_t td_ramping_support;
uint8_t dbr_ramping_support;
uint8_t gc_didt_support;
uint8_t psm_didt_support;
uint8_t thermal_support;
uint8_t fw_ctf_enabled;
uint8_t led_dpm_enabled;
uint8_t fan_control_support;
uint8_t ulv_support;
uint8_t od8_feature_enable;
uint8_t disable_water_mark;
uint8_t disable_workload_policy;
uint32_t force_workload_policy_mask;
uint8_t disable_3d_fs_detection;
uint8_t disable_pp_tuning;
uint8_t disable_xlpp_tuning;
uint32_t perf_ui_tuning_profile_turbo;
uint32_t perf_ui_tuning_profile_powerSave;
uint32_t perf_ui_tuning_profile_xl;
uint16_t zrpm_stop_temp;
uint16_t zrpm_start_temp;
uint32_t stable_pstate_sclk_dpm_percentage;
uint8_t fps_support;
uint8_t vr0hot;
uint8_t vr1hot;
uint8_t disable_auto_wattman;
uint32_t auto_wattman_debug;
uint32_t auto_wattman_sample_period;
uint32_t fclk_gfxclk_ratio;
uint8_t auto_wattman_threshold;
uint8_t log_avfs_param;
uint8_t enable_enginess;
uint8_t custom_fan_support;
uint8_t disable_pcc_limit_control;
uint8_t gfxoff_controlled_by_driver;
};
struct vega20_odn_clock_voltage_dependency_table {
uint32_t count;
struct phm_ppt_v1_clock_voltage_dependency_record
entries[MAX_REGULAR_DPM_NUMBER];
};
struct vega20_odn_dpm_table {
struct vega20_odn_dpm_control control_gfxclk_state;
struct vega20_odn_dpm_control control_memclk_state;
struct phm_odn_clock_levels odn_core_clock_dpm_levels;
struct phm_odn_clock_levels odn_memory_clock_dpm_levels;
struct vega20_odn_clock_voltage_dependency_table vdd_dependency_on_sclk;
struct vega20_odn_clock_voltage_dependency_table vdd_dependency_on_mclk;
struct vega20_odn_clock_voltage_dependency_table vdd_dependency_on_socclk;
uint32_t odn_mclk_min_limit;
};
struct vega20_odn_fan_table {
uint32_t target_fan_speed;
uint32_t target_temperature;
uint32_t min_performance_clock;
uint32_t min_fan_limit;
bool force_fan_pwm;
};
struct vega20_odn_temp_table {
uint16_t target_operating_temp;
uint16_t default_target_operating_temp;
uint16_t operating_temp_min_limit;
uint16_t operating_temp_max_limit;
uint16_t operating_temp_step;
};
struct vega20_odn_data {
uint32_t apply_overdrive_next_settings_mask;
uint32_t overdrive_next_state;
uint32_t overdrive_next_capabilities;
uint32_t odn_sclk_dpm_enable_mask;
uint32_t odn_mclk_dpm_enable_mask;
struct vega20_odn_dpm_table odn_dpm_table;
struct vega20_odn_fan_table odn_fan_table;
struct vega20_odn_temp_table odn_temp_table;
};
enum OD8_FEATURE_ID
{
OD8_GFXCLK_LIMITS = 1 << 0,
OD8_GFXCLK_CURVE = 1 << 1,
OD8_UCLK_MAX = 1 << 2,
OD8_POWER_LIMIT = 1 << 3,
OD8_ACOUSTIC_LIMIT_SCLK = 1 << 4, //FanMaximumRpm
OD8_FAN_SPEED_MIN = 1 << 5, //FanMinimumPwm
OD8_TEMPERATURE_FAN = 1 << 6, //FanTargetTemperature
OD8_TEMPERATURE_SYSTEM = 1 << 7, //MaxOpTemp
OD8_MEMORY_TIMING_TUNE = 1 << 8,
OD8_FAN_ZERO_RPM_CONTROL = 1 << 9
};
enum OD8_SETTING_ID
{
OD8_SETTING_GFXCLK_FMIN = 0,
OD8_SETTING_GFXCLK_FMAX,
OD8_SETTING_GFXCLK_FREQ1,
OD8_SETTING_GFXCLK_VOLTAGE1,
OD8_SETTING_GFXCLK_FREQ2,
OD8_SETTING_GFXCLK_VOLTAGE2,
OD8_SETTING_GFXCLK_FREQ3,
OD8_SETTING_GFXCLK_VOLTAGE3,
OD8_SETTING_UCLK_FMAX,
OD8_SETTING_POWER_PERCENTAGE,
OD8_SETTING_FAN_ACOUSTIC_LIMIT,
OD8_SETTING_FAN_MIN_SPEED,
OD8_SETTING_FAN_TARGET_TEMP,
OD8_SETTING_OPERATING_TEMP_MAX,
OD8_SETTING_AC_TIMING,
OD8_SETTING_FAN_ZERO_RPM_CONTROL,
OD8_SETTING_COUNT
};
struct vega20_od8_single_setting {
uint32_t feature_id;
int32_t min_value;
int32_t max_value;
int32_t current_value;
int32_t default_value;
};
struct vega20_od8_settings {
uint32_t overdrive8_capabilities;
struct vega20_od8_single_setting od8_settings_array[OD8_SETTING_COUNT];
};
struct vega20_hwmgr {
struct vega20_dpm_table dpm_table;
struct vega20_dpm_table golden_dpm_table;
struct vega20_registry_data registry_data;
struct vega20_vbios_boot_state vbios_boot_state;
struct vega20_mclk_latency_table mclk_latency_table;
struct vega20_max_sustainable_clocks max_sustainable_clocks;
struct vega20_leakage_voltage vddc_leakage;
uint32_t vddc_control;
struct pp_atomfwctrl_voltage_table vddc_voltage_table;
uint32_t mvdd_control;
struct pp_atomfwctrl_voltage_table mvdd_voltage_table;
uint32_t vddci_control;
struct pp_atomfwctrl_voltage_table vddci_voltage_table;
uint32_t active_auto_throttle_sources;
struct vega20_bacos bacos;
/* ---- General data ---- */
uint8_t need_update_dpm_table;
bool cac_enabled;
bool battery_state;
bool is_tlu_enabled;
bool avfs_exist;
uint32_t low_sclk_interrupt_threshold;
uint32_t total_active_cus;
uint32_t water_marks_bitmap;
struct vega20_display_timing display_timing;
/* ---- Vega20 Dyn Register Settings ---- */
uint32_t debug_settings;
uint32_t lowest_uclk_reserved_for_ulv;
uint32_t gfxclk_average_alpha;
uint32_t socclk_average_alpha;
uint32_t uclk_average_alpha;
uint32_t gfx_activity_average_alpha;
uint32_t display_voltage_mode;
uint32_t dcef_clk_quad_eqn_a;
uint32_t dcef_clk_quad_eqn_b;
uint32_t dcef_clk_quad_eqn_c;
uint32_t disp_clk_quad_eqn_a;
uint32_t disp_clk_quad_eqn_b;
uint32_t disp_clk_quad_eqn_c;
uint32_t pixel_clk_quad_eqn_a;
uint32_t pixel_clk_quad_eqn_b;
uint32_t pixel_clk_quad_eqn_c;
uint32_t phy_clk_quad_eqn_a;
uint32_t phy_clk_quad_eqn_b;
uint32_t phy_clk_quad_eqn_c;
/* ---- Thermal Temperature Setting ---- */
struct vega20_dpmlevel_enable_mask dpm_level_enable_mask;
/* ---- Power Gating States ---- */
bool uvd_power_gated;
bool vce_power_gated;
bool samu_power_gated;
bool need_long_memory_training;
/* Internal settings to apply the application power optimization parameters */
bool apply_optimized_settings;
uint32_t disable_dpm_mask;
/* ---- Overdrive next setting ---- */
struct vega20_odn_data odn_data;
bool gfxclk_overdrive;
bool memclk_overdrive;
/* ---- Overdrive8 Setting ---- */
struct vega20_od8_settings od8_settings;
/* ---- Workload Mask ---- */
uint32_t workload_mask;
/* ---- SMU9 ---- */
uint32_t smu_version;
struct smu_features smu_features[GNLD_FEATURES_MAX];
struct vega20_smc_state_table smc_state_table;
/* ---- Gfxoff ---- */
bool gfxoff_allowed;
uint32_t counter_gfxoff;
unsigned long metrics_time;
SmuMetrics_t metrics_table;
struct gpu_metrics_v1_0 gpu_metrics_table;
bool pcie_parameters_override;
uint32_t pcie_gen_level1;
uint32_t pcie_width_level1;
bool is_custom_profile_set;
};
#define VEGA20_DPM2_NEAR_TDP_DEC 10
#define VEGA20_DPM2_ABOVE_SAFE_INC 5
#define VEGA20_DPM2_BELOW_SAFE_INC 20
#define VEGA20_DPM2_LTA_WINDOW_SIZE 7
#define VEGA20_DPM2_LTS_TRUNCATE 0
#define VEGA20_DPM2_TDP_SAFE_LIMIT_PERCENT 80
#define VEGA20_DPM2_MAXPS_PERCENT_M 90
#define VEGA20_DPM2_MAXPS_PERCENT_H 90
#define VEGA20_DPM2_PWREFFICIENCYRATIO_MARGIN 50
#define VEGA20_DPM2_SQ_RAMP_MAX_POWER 0x3FFF
#define VEGA20_DPM2_SQ_RAMP_MIN_POWER 0x12
#define VEGA20_DPM2_SQ_RAMP_MAX_POWER_DELTA 0x15
#define VEGA20_DPM2_SQ_RAMP_SHORT_TERM_INTERVAL_SIZE 0x1E
#define VEGA20_DPM2_SQ_RAMP_LONG_TERM_INTERVAL_RATIO 0xF
#define VEGA20_VOLTAGE_CONTROL_NONE 0x0
#define VEGA20_VOLTAGE_CONTROL_BY_GPIO 0x1
#define VEGA20_VOLTAGE_CONTROL_BY_SVID2 0x2
#define VEGA20_VOLTAGE_CONTROL_MERGED 0x3
/* To convert to Q8.8 format for firmware */
#define VEGA20_Q88_FORMAT_CONVERSION_UNIT 256
#define VEGA20_UNUSED_GPIO_PIN 0x7F
#define VEGA20_THERM_OUT_MODE_DISABLE 0x0
#define VEGA20_THERM_OUT_MODE_THERM_ONLY 0x1
#define VEGA20_THERM_OUT_MODE_THERM_VRHOT 0x2
#define PPVEGA20_VEGA20DISPLAYVOLTAGEMODE_DFLT 0xffffffff
#define PPREGKEY_VEGA20QUADRATICEQUATION_DFLT 0xffffffff
#define PPVEGA20_VEGA20GFXCLKAVERAGEALPHA_DFLT 25 /* 10% * 255 = 25 */
#define PPVEGA20_VEGA20SOCCLKAVERAGEALPHA_DFLT 25 /* 10% * 255 = 25 */
#define PPVEGA20_VEGA20UCLKCLKAVERAGEALPHA_DFLT 25 /* 10% * 255 = 25 */
#define PPVEGA20_VEGA20GFXACTIVITYAVERAGEALPHA_DFLT 25 /* 10% * 255 = 25 */
#define PPVEGA20_VEGA20LOWESTUCLKRESERVEDFORULV_DFLT 0xffffffff
#define PPVEGA20_VEGA20DISPLAYVOLTAGEMODE_DFLT 0xffffffff
#define PPREGKEY_VEGA20QUADRATICEQUATION_DFLT 0xffffffff
#define VEGA20_UMD_PSTATE_GFXCLK_LEVEL 0x3
#define VEGA20_UMD_PSTATE_SOCCLK_LEVEL 0x3
#define VEGA20_UMD_PSTATE_MCLK_LEVEL 0x2
#define VEGA20_UMD_PSTATE_UVDCLK_LEVEL 0x3
#define VEGA20_UMD_PSTATE_VCEMCLK_LEVEL 0x3
#endif /* _VEGA20_HWMGR_H_ */

View File

@@ -0,0 +1,36 @@
/*
* Copyright 2018 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.
*
*/
#ifndef VEGA20_INC_H
#define VEGA20_INC_H
#include "asic_reg/thm/thm_11_0_2_offset.h"
#include "asic_reg/thm/thm_11_0_2_sh_mask.h"
#include "asic_reg/mp/mp_9_0_offset.h"
#include "asic_reg/mp/mp_9_0_sh_mask.h"
#include "asic_reg/nbio/nbio_7_4_offset.h"
#include "asic_reg/nbio/nbio_7_4_sh_mask.h"
#endif

View File

@@ -0,0 +1,72 @@
/*
* Copyright 2018 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 "hwmgr.h"
#include "vega20_hwmgr.h"
#include "vega20_powertune.h"
#include "vega20_smumgr.h"
#include "vega20_ppsmc.h"
#include "vega20_inc.h"
#include "pp_debug.h"
int vega20_set_power_limit(struct pp_hwmgr *hwmgr, uint32_t n)
{
struct vega20_hwmgr *data =
(struct vega20_hwmgr *)(hwmgr->backend);
if (data->smu_features[GNLD_PPT].enabled)
return smum_send_msg_to_smc_with_parameter(hwmgr,
PPSMC_MSG_SetPptLimit, n,
NULL);
return 0;
}
int vega20_validate_power_level_request(struct pp_hwmgr *hwmgr,
uint32_t tdp_percentage_adjustment, uint32_t tdp_absolute_value_adjustment)
{
return (tdp_percentage_adjustment > hwmgr->platform_descriptor.TDPLimit) ? -1 : 0;
}
static int vega20_set_overdrive_target_percentage(struct pp_hwmgr *hwmgr,
uint32_t adjust_percent)
{
return smum_send_msg_to_smc_with_parameter(hwmgr,
PPSMC_MSG_OverDriveSetPercentage, adjust_percent,
NULL);
}
int vega20_power_control_set_level(struct pp_hwmgr *hwmgr)
{
int adjust_percent, result = 0;
if (PP_CAP(PHM_PlatformCaps_PowerContainment)) {
adjust_percent =
hwmgr->platform_descriptor.TDPAdjustmentPolarity ?
hwmgr->platform_descriptor.TDPAdjustment :
(-1 * hwmgr->platform_descriptor.TDPAdjustment);
result = vega20_set_overdrive_target_percentage(hwmgr,
(uint32_t)adjust_percent);
}
return result;
}

View File

@@ -0,0 +1,32 @@
/*
* Copyright 2018 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.
*
*/
#ifndef _VEGA20_POWERTUNE_H_
#define _VEGA20_POWERTUNE_H_
int vega20_set_power_limit(struct pp_hwmgr *hwmgr, uint32_t n);
int vega20_power_control_set_level(struct pp_hwmgr *hwmgr);
int vega20_validate_power_level_request(struct pp_hwmgr *hwmgr,
uint32_t tdp_percentage_adjustment,
uint32_t tdp_absolute_value_adjustment);
#endif /* _VEGA20_POWERTUNE_H_ */

View File

@@ -0,0 +1,142 @@
/*
* Copyright 2018 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.
*
*/
#ifndef _VEGA20_PPTABLE_H_
#define _VEGA20_PPTABLE_H_
#pragma pack(push, 1)
#define ATOM_VEGA20_PP_THERMALCONTROLLER_NONE 0
#define ATOM_VEGA20_PP_THERMALCONTROLLER_VEGA20 26
#define ATOM_VEGA20_PP_PLATFORM_CAP_POWERPLAY 0x1
#define ATOM_VEGA20_PP_PLATFORM_CAP_SBIOSPOWERSOURCE 0x2
#define ATOM_VEGA20_PP_PLATFORM_CAP_HARDWAREDC 0x4
#define ATOM_VEGA20_PP_PLATFORM_CAP_BACO 0x8
#define ATOM_VEGA20_PP_PLATFORM_CAP_BAMACO 0x10
#define ATOM_VEGA20_PP_PLATFORM_CAP_ENABLESHADOWPSTATE 0x20
#define ATOM_VEGA20_TABLE_REVISION_VEGA20 11
#define ATOM_VEGA20_ODFEATURE_MAX_COUNT 32
#define ATOM_VEGA20_ODSETTING_MAX_COUNT 32
#define ATOM_VEGA20_PPCLOCK_MAX_COUNT 16
enum ATOM_VEGA20_ODFEATURE_ID {
ATOM_VEGA20_ODFEATURE_GFXCLK_LIMITS = 0,
ATOM_VEGA20_ODFEATURE_GFXCLK_CURVE,
ATOM_VEGA20_ODFEATURE_UCLK_MAX,
ATOM_VEGA20_ODFEATURE_POWER_LIMIT,
ATOM_VEGA20_ODFEATURE_FAN_ACOUSTIC_LIMIT, //FanMaximumRpm
ATOM_VEGA20_ODFEATURE_FAN_SPEED_MIN, //FanMinimumPwm
ATOM_VEGA20_ODFEATURE_TEMPERATURE_FAN, //FanTargetTemperature
ATOM_VEGA20_ODFEATURE_TEMPERATURE_SYSTEM, //MaxOpTemp
ATOM_VEGA20_ODFEATURE_MEMORY_TIMING_TUNE,
ATOM_VEGA20_ODFEATURE_FAN_ZERO_RPM_CONTROL,
ATOM_VEGA20_ODFEATURE_COUNT,
};
enum ATOM_VEGA20_ODSETTING_ID {
ATOM_VEGA20_ODSETTING_GFXCLKFMAX = 0,
ATOM_VEGA20_ODSETTING_GFXCLKFMIN,
ATOM_VEGA20_ODSETTING_VDDGFXCURVEFREQ_P1,
ATOM_VEGA20_ODSETTING_VDDGFXCURVEVOLTAGEOFFSET_P1,
ATOM_VEGA20_ODSETTING_VDDGFXCURVEFREQ_P2,
ATOM_VEGA20_ODSETTING_VDDGFXCURVEVOLTAGEOFFSET_P2,
ATOM_VEGA20_ODSETTING_VDDGFXCURVEFREQ_P3,
ATOM_VEGA20_ODSETTING_VDDGFXCURVEVOLTAGEOFFSET_P3,
ATOM_VEGA20_ODSETTING_UCLKFMAX,
ATOM_VEGA20_ODSETTING_POWERPERCENTAGE,
ATOM_VEGA20_ODSETTING_FANRPMMIN,
ATOM_VEGA20_ODSETTING_FANRPMACOUSTICLIMIT,
ATOM_VEGA20_ODSETTING_FANTARGETTEMPERATURE,
ATOM_VEGA20_ODSETTING_OPERATINGTEMPMAX,
ATOM_VEGA20_ODSETTING_COUNT,
};
typedef enum ATOM_VEGA20_ODSETTING_ID ATOM_VEGA20_ODSETTING_ID;
typedef struct _ATOM_VEGA20_OVERDRIVE8_RECORD
{
UCHAR ucODTableRevision;
ULONG ODFeatureCount;
UCHAR ODFeatureCapabilities [ATOM_VEGA20_ODFEATURE_MAX_COUNT]; //OD feature support flags
ULONG ODSettingCount;
ULONG ODSettingsMax [ATOM_VEGA20_ODSETTING_MAX_COUNT]; //Upper Limit for each OD Setting
ULONG ODSettingsMin [ATOM_VEGA20_ODSETTING_MAX_COUNT]; //Lower Limit for each OD Setting
} ATOM_VEGA20_OVERDRIVE8_RECORD;
enum ATOM_VEGA20_PPCLOCK_ID {
ATOM_VEGA20_PPCLOCK_GFXCLK = 0,
ATOM_VEGA20_PPCLOCK_VCLK,
ATOM_VEGA20_PPCLOCK_DCLK,
ATOM_VEGA20_PPCLOCK_ECLK,
ATOM_VEGA20_PPCLOCK_SOCCLK,
ATOM_VEGA20_PPCLOCK_UCLK,
ATOM_VEGA20_PPCLOCK_FCLK,
ATOM_VEGA20_PPCLOCK_DCEFCLK,
ATOM_VEGA20_PPCLOCK_DISPCLK,
ATOM_VEGA20_PPCLOCK_PIXCLK,
ATOM_VEGA20_PPCLOCK_PHYCLK,
ATOM_VEGA20_PPCLOCK_COUNT,
};
typedef enum ATOM_VEGA20_PPCLOCK_ID ATOM_VEGA20_PPCLOCK_ID;
typedef struct _ATOM_VEGA20_POWER_SAVING_CLOCK_RECORD
{
UCHAR ucTableRevision;
ULONG PowerSavingClockCount; // Count of PowerSavingClock Mode
ULONG PowerSavingClockMax [ATOM_VEGA20_PPCLOCK_MAX_COUNT]; // PowerSavingClock Mode Clock Maximum array In MHz
ULONG PowerSavingClockMin [ATOM_VEGA20_PPCLOCK_MAX_COUNT]; // PowerSavingClock Mode Clock Minimum array In MHz
} ATOM_VEGA20_POWER_SAVING_CLOCK_RECORD;
typedef struct _ATOM_VEGA20_POWERPLAYTABLE
{
struct atom_common_table_header sHeader;
UCHAR ucTableRevision;
USHORT usTableSize;
ULONG ulGoldenPPID;
ULONG ulGoldenRevision;
USHORT usFormatID;
ULONG ulPlatformCaps;
UCHAR ucThermalControllerType;
USHORT usSmallPowerLimit1;
USHORT usSmallPowerLimit2;
USHORT usBoostPowerLimit;
USHORT usODTurboPowerLimit;
USHORT usODPowerSavePowerLimit;
USHORT usSoftwareShutdownTemp;
ATOM_VEGA20_POWER_SAVING_CLOCK_RECORD PowerSavingClockTable; //PowerSavingClock Mode Clock Min/Max array
ATOM_VEGA20_OVERDRIVE8_RECORD OverDrive8Table; //OverDrive8 Feature capabilities and Settings Range (Max and Min)
USHORT usReserve[5];
PPTable_t smcPPTable;
} ATOM_Vega20_POWERPLAYTABLE;
#pragma pack(pop)
#endif

View File

@@ -0,0 +1,970 @@
/*
* Copyright 2018 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/module.h>
#include <linux/slab.h>
#include <linux/fb.h>
#include "smu11_driver_if.h"
#include "vega20_processpptables.h"
#include "ppatomfwctrl.h"
#include "atomfirmware.h"
#include "pp_debug.h"
#include "cgs_common.h"
#include "vega20_pptable.h"
#define VEGA20_FAN_TARGET_TEMPERATURE_OVERRIDE 105
static void set_hw_cap(struct pp_hwmgr *hwmgr, bool enable,
enum phm_platform_caps cap)
{
if (enable)
phm_cap_set(hwmgr->platform_descriptor.platformCaps, cap);
else
phm_cap_unset(hwmgr->platform_descriptor.platformCaps, cap);
}
static const void *get_powerplay_table(struct pp_hwmgr *hwmgr)
{
int index = GetIndexIntoMasterDataTable(powerplayinfo);
u16 size;
u8 frev, crev;
const void *table_address = hwmgr->soft_pp_table;
if (!table_address) {
table_address = (ATOM_Vega20_POWERPLAYTABLE *)
smu_atom_get_data_table(hwmgr->adev, index,
&size, &frev, &crev);
hwmgr->soft_pp_table = table_address;
hwmgr->soft_pp_table_size = size;
}
return table_address;
}
#if 0
static void dump_pptable(PPTable_t *pptable)
{
int i;
pr_info("Version = 0x%08x\n", pptable->Version);
pr_info("FeaturesToRun[0] = 0x%08x\n", pptable->FeaturesToRun[0]);
pr_info("FeaturesToRun[1] = 0x%08x\n", pptable->FeaturesToRun[1]);
pr_info("SocketPowerLimitAc0 = %d\n", pptable->SocketPowerLimitAc0);
pr_info("SocketPowerLimitAc0Tau = %d\n", pptable->SocketPowerLimitAc0Tau);
pr_info("SocketPowerLimitAc1 = %d\n", pptable->SocketPowerLimitAc1);
pr_info("SocketPowerLimitAc1Tau = %d\n", pptable->SocketPowerLimitAc1Tau);
pr_info("SocketPowerLimitAc2 = %d\n", pptable->SocketPowerLimitAc2);
pr_info("SocketPowerLimitAc2Tau = %d\n", pptable->SocketPowerLimitAc2Tau);
pr_info("SocketPowerLimitAc3 = %d\n", pptable->SocketPowerLimitAc3);
pr_info("SocketPowerLimitAc3Tau = %d\n", pptable->SocketPowerLimitAc3Tau);
pr_info("SocketPowerLimitDc = %d\n", pptable->SocketPowerLimitDc);
pr_info("SocketPowerLimitDcTau = %d\n", pptable->SocketPowerLimitDcTau);
pr_info("TdcLimitSoc = %d\n", pptable->TdcLimitSoc);
pr_info("TdcLimitSocTau = %d\n", pptable->TdcLimitSocTau);
pr_info("TdcLimitGfx = %d\n", pptable->TdcLimitGfx);
pr_info("TdcLimitGfxTau = %d\n", pptable->TdcLimitGfxTau);
pr_info("TedgeLimit = %d\n", pptable->TedgeLimit);
pr_info("ThotspotLimit = %d\n", pptable->ThotspotLimit);
pr_info("ThbmLimit = %d\n", pptable->ThbmLimit);
pr_info("Tvr_gfxLimit = %d\n", pptable->Tvr_gfxLimit);
pr_info("Tvr_memLimit = %d\n", pptable->Tvr_memLimit);
pr_info("Tliquid1Limit = %d\n", pptable->Tliquid1Limit);
pr_info("Tliquid2Limit = %d\n", pptable->Tliquid2Limit);
pr_info("TplxLimit = %d\n", pptable->TplxLimit);
pr_info("FitLimit = %d\n", pptable->FitLimit);
pr_info("PpmPowerLimit = %d\n", pptable->PpmPowerLimit);
pr_info("PpmTemperatureThreshold = %d\n", pptable->PpmTemperatureThreshold);
pr_info("MemoryOnPackage = 0x%02x\n", pptable->MemoryOnPackage);
pr_info("padding8_limits = 0x%02x\n", pptable->padding8_limits);
pr_info("Tvr_SocLimit = %d\n", pptable->Tvr_SocLimit);
pr_info("UlvVoltageOffsetSoc = %d\n", pptable->UlvVoltageOffsetSoc);
pr_info("UlvVoltageOffsetGfx = %d\n", pptable->UlvVoltageOffsetGfx);
pr_info("UlvSmnclkDid = %d\n", pptable->UlvSmnclkDid);
pr_info("UlvMp1clkDid = %d\n", pptable->UlvMp1clkDid);
pr_info("UlvGfxclkBypass = %d\n", pptable->UlvGfxclkBypass);
pr_info("Padding234 = 0x%02x\n", pptable->Padding234);
pr_info("MinVoltageGfx = %d\n", pptable->MinVoltageGfx);
pr_info("MinVoltageSoc = %d\n", pptable->MinVoltageSoc);
pr_info("MaxVoltageGfx = %d\n", pptable->MaxVoltageGfx);
pr_info("MaxVoltageSoc = %d\n", pptable->MaxVoltageSoc);
pr_info("LoadLineResistanceGfx = %d\n", pptable->LoadLineResistanceGfx);
pr_info("LoadLineResistanceSoc = %d\n", pptable->LoadLineResistanceSoc);
pr_info("[PPCLK_GFXCLK]\n"
" .VoltageMode = 0x%02x\n"
" .SnapToDiscrete = 0x%02x\n"
" .NumDiscreteLevels = 0x%02x\n"
" .padding = 0x%02x\n"
" .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n"
" .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n",
pptable->DpmDescriptor[PPCLK_GFXCLK].VoltageMode,
pptable->DpmDescriptor[PPCLK_GFXCLK].SnapToDiscrete,
pptable->DpmDescriptor[PPCLK_GFXCLK].NumDiscreteLevels,
pptable->DpmDescriptor[PPCLK_GFXCLK].padding,
pptable->DpmDescriptor[PPCLK_GFXCLK].ConversionToAvfsClk.m,
pptable->DpmDescriptor[PPCLK_GFXCLK].ConversionToAvfsClk.b,
pptable->DpmDescriptor[PPCLK_GFXCLK].SsCurve.a,
pptable->DpmDescriptor[PPCLK_GFXCLK].SsCurve.b,
pptable->DpmDescriptor[PPCLK_GFXCLK].SsCurve.c);
pr_info("[PPCLK_VCLK]\n"
" .VoltageMode = 0x%02x\n"
" .SnapToDiscrete = 0x%02x\n"
" .NumDiscreteLevels = 0x%02x\n"
" .padding = 0x%02x\n"
" .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n"
" .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n",
pptable->DpmDescriptor[PPCLK_VCLK].VoltageMode,
pptable->DpmDescriptor[PPCLK_VCLK].SnapToDiscrete,
pptable->DpmDescriptor[PPCLK_VCLK].NumDiscreteLevels,
pptable->DpmDescriptor[PPCLK_VCLK].padding,
pptable->DpmDescriptor[PPCLK_VCLK].ConversionToAvfsClk.m,
pptable->DpmDescriptor[PPCLK_VCLK].ConversionToAvfsClk.b,
pptable->DpmDescriptor[PPCLK_VCLK].SsCurve.a,
pptable->DpmDescriptor[PPCLK_VCLK].SsCurve.b,
pptable->DpmDescriptor[PPCLK_VCLK].SsCurve.c);
pr_info("[PPCLK_DCLK]\n"
" .VoltageMode = 0x%02x\n"
" .SnapToDiscrete = 0x%02x\n"
" .NumDiscreteLevels = 0x%02x\n"
" .padding = 0x%02x\n"
" .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n"
" .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n",
pptable->DpmDescriptor[PPCLK_DCLK].VoltageMode,
pptable->DpmDescriptor[PPCLK_DCLK].SnapToDiscrete,
pptable->DpmDescriptor[PPCLK_DCLK].NumDiscreteLevels,
pptable->DpmDescriptor[PPCLK_DCLK].padding,
pptable->DpmDescriptor[PPCLK_DCLK].ConversionToAvfsClk.m,
pptable->DpmDescriptor[PPCLK_DCLK].ConversionToAvfsClk.b,
pptable->DpmDescriptor[PPCLK_DCLK].SsCurve.a,
pptable->DpmDescriptor[PPCLK_DCLK].SsCurve.b,
pptable->DpmDescriptor[PPCLK_DCLK].SsCurve.c);
pr_info("[PPCLK_ECLK]\n"
" .VoltageMode = 0x%02x\n"
" .SnapToDiscrete = 0x%02x\n"
" .NumDiscreteLevels = 0x%02x\n"
" .padding = 0x%02x\n"
" .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n"
" .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n",
pptable->DpmDescriptor[PPCLK_ECLK].VoltageMode,
pptable->DpmDescriptor[PPCLK_ECLK].SnapToDiscrete,
pptable->DpmDescriptor[PPCLK_ECLK].NumDiscreteLevels,
pptable->DpmDescriptor[PPCLK_ECLK].padding,
pptable->DpmDescriptor[PPCLK_ECLK].ConversionToAvfsClk.m,
pptable->DpmDescriptor[PPCLK_ECLK].ConversionToAvfsClk.b,
pptable->DpmDescriptor[PPCLK_ECLK].SsCurve.a,
pptable->DpmDescriptor[PPCLK_ECLK].SsCurve.b,
pptable->DpmDescriptor[PPCLK_ECLK].SsCurve.c);
pr_info("[PPCLK_SOCCLK]\n"
" .VoltageMode = 0x%02x\n"
" .SnapToDiscrete = 0x%02x\n"
" .NumDiscreteLevels = 0x%02x\n"
" .padding = 0x%02x\n"
" .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n"
" .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n",
pptable->DpmDescriptor[PPCLK_SOCCLK].VoltageMode,
pptable->DpmDescriptor[PPCLK_SOCCLK].SnapToDiscrete,
pptable->DpmDescriptor[PPCLK_SOCCLK].NumDiscreteLevels,
pptable->DpmDescriptor[PPCLK_SOCCLK].padding,
pptable->DpmDescriptor[PPCLK_SOCCLK].ConversionToAvfsClk.m,
pptable->DpmDescriptor[PPCLK_SOCCLK].ConversionToAvfsClk.b,
pptable->DpmDescriptor[PPCLK_SOCCLK].SsCurve.a,
pptable->DpmDescriptor[PPCLK_SOCCLK].SsCurve.b,
pptable->DpmDescriptor[PPCLK_SOCCLK].SsCurve.c);
pr_info("[PPCLK_UCLK]\n"
" .VoltageMode = 0x%02x\n"
" .SnapToDiscrete = 0x%02x\n"
" .NumDiscreteLevels = 0x%02x\n"
" .padding = 0x%02x\n"
" .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n"
" .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n",
pptable->DpmDescriptor[PPCLK_UCLK].VoltageMode,
pptable->DpmDescriptor[PPCLK_UCLK].SnapToDiscrete,
pptable->DpmDescriptor[PPCLK_UCLK].NumDiscreteLevels,
pptable->DpmDescriptor[PPCLK_UCLK].padding,
pptable->DpmDescriptor[PPCLK_UCLK].ConversionToAvfsClk.m,
pptable->DpmDescriptor[PPCLK_UCLK].ConversionToAvfsClk.b,
pptable->DpmDescriptor[PPCLK_UCLK].SsCurve.a,
pptable->DpmDescriptor[PPCLK_UCLK].SsCurve.b,
pptable->DpmDescriptor[PPCLK_UCLK].SsCurve.c);
pr_info("[PPCLK_DCEFCLK]\n"
" .VoltageMode = 0x%02x\n"
" .SnapToDiscrete = 0x%02x\n"
" .NumDiscreteLevels = 0x%02x\n"
" .padding = 0x%02x\n"
" .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n"
" .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n",
pptable->DpmDescriptor[PPCLK_DCEFCLK].VoltageMode,
pptable->DpmDescriptor[PPCLK_DCEFCLK].SnapToDiscrete,
pptable->DpmDescriptor[PPCLK_DCEFCLK].NumDiscreteLevels,
pptable->DpmDescriptor[PPCLK_DCEFCLK].padding,
pptable->DpmDescriptor[PPCLK_DCEFCLK].ConversionToAvfsClk.m,
pptable->DpmDescriptor[PPCLK_DCEFCLK].ConversionToAvfsClk.b,
pptable->DpmDescriptor[PPCLK_DCEFCLK].SsCurve.a,
pptable->DpmDescriptor[PPCLK_DCEFCLK].SsCurve.b,
pptable->DpmDescriptor[PPCLK_DCEFCLK].SsCurve.c);
pr_info("[PPCLK_DISPCLK]\n"
" .VoltageMode = 0x%02x\n"
" .SnapToDiscrete = 0x%02x\n"
" .NumDiscreteLevels = 0x%02x\n"
" .padding = 0x%02x\n"
" .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n"
" .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n",
pptable->DpmDescriptor[PPCLK_DISPCLK].VoltageMode,
pptable->DpmDescriptor[PPCLK_DISPCLK].SnapToDiscrete,
pptable->DpmDescriptor[PPCLK_DISPCLK].NumDiscreteLevels,
pptable->DpmDescriptor[PPCLK_DISPCLK].padding,
pptable->DpmDescriptor[PPCLK_DISPCLK].ConversionToAvfsClk.m,
pptable->DpmDescriptor[PPCLK_DISPCLK].ConversionToAvfsClk.b,
pptable->DpmDescriptor[PPCLK_DISPCLK].SsCurve.a,
pptable->DpmDescriptor[PPCLK_DISPCLK].SsCurve.b,
pptable->DpmDescriptor[PPCLK_DISPCLK].SsCurve.c);
pr_info("[PPCLK_PIXCLK]\n"
" .VoltageMode = 0x%02x\n"
" .SnapToDiscrete = 0x%02x\n"
" .NumDiscreteLevels = 0x%02x\n"
" .padding = 0x%02x\n"
" .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n"
" .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n",
pptable->DpmDescriptor[PPCLK_PIXCLK].VoltageMode,
pptable->DpmDescriptor[PPCLK_PIXCLK].SnapToDiscrete,
pptable->DpmDescriptor[PPCLK_PIXCLK].NumDiscreteLevels,
pptable->DpmDescriptor[PPCLK_PIXCLK].padding,
pptable->DpmDescriptor[PPCLK_PIXCLK].ConversionToAvfsClk.m,
pptable->DpmDescriptor[PPCLK_PIXCLK].ConversionToAvfsClk.b,
pptable->DpmDescriptor[PPCLK_PIXCLK].SsCurve.a,
pptable->DpmDescriptor[PPCLK_PIXCLK].SsCurve.b,
pptable->DpmDescriptor[PPCLK_PIXCLK].SsCurve.c);
pr_info("[PPCLK_PHYCLK]\n"
" .VoltageMode = 0x%02x\n"
" .SnapToDiscrete = 0x%02x\n"
" .NumDiscreteLevels = 0x%02x\n"
" .padding = 0x%02x\n"
" .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n"
" .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n",
pptable->DpmDescriptor[PPCLK_PHYCLK].VoltageMode,
pptable->DpmDescriptor[PPCLK_PHYCLK].SnapToDiscrete,
pptable->DpmDescriptor[PPCLK_PHYCLK].NumDiscreteLevels,
pptable->DpmDescriptor[PPCLK_PHYCLK].padding,
pptable->DpmDescriptor[PPCLK_PHYCLK].ConversionToAvfsClk.m,
pptable->DpmDescriptor[PPCLK_PHYCLK].ConversionToAvfsClk.b,
pptable->DpmDescriptor[PPCLK_PHYCLK].SsCurve.a,
pptable->DpmDescriptor[PPCLK_PHYCLK].SsCurve.b,
pptable->DpmDescriptor[PPCLK_PHYCLK].SsCurve.c);
pr_info("[PPCLK_FCLK]\n"
" .VoltageMode = 0x%02x\n"
" .SnapToDiscrete = 0x%02x\n"
" .NumDiscreteLevels = 0x%02x\n"
" .padding = 0x%02x\n"
" .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n"
" .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n",
pptable->DpmDescriptor[PPCLK_FCLK].VoltageMode,
pptable->DpmDescriptor[PPCLK_FCLK].SnapToDiscrete,
pptable->DpmDescriptor[PPCLK_FCLK].NumDiscreteLevels,
pptable->DpmDescriptor[PPCLK_FCLK].padding,
pptable->DpmDescriptor[PPCLK_FCLK].ConversionToAvfsClk.m,
pptable->DpmDescriptor[PPCLK_FCLK].ConversionToAvfsClk.b,
pptable->DpmDescriptor[PPCLK_FCLK].SsCurve.a,
pptable->DpmDescriptor[PPCLK_FCLK].SsCurve.b,
pptable->DpmDescriptor[PPCLK_FCLK].SsCurve.c);
pr_info("FreqTableGfx\n");
for (i = 0; i < NUM_GFXCLK_DPM_LEVELS; i++)
pr_info(" .[%02d] = %d\n", i, pptable->FreqTableGfx[i]);
pr_info("FreqTableVclk\n");
for (i = 0; i < NUM_VCLK_DPM_LEVELS; i++)
pr_info(" .[%02d] = %d\n", i, pptable->FreqTableVclk[i]);
pr_info("FreqTableDclk\n");
for (i = 0; i < NUM_DCLK_DPM_LEVELS; i++)
pr_info(" .[%02d] = %d\n", i, pptable->FreqTableDclk[i]);
pr_info("FreqTableEclk\n");
for (i = 0; i < NUM_ECLK_DPM_LEVELS; i++)
pr_info(" .[%02d] = %d\n", i, pptable->FreqTableEclk[i]);
pr_info("FreqTableSocclk\n");
for (i = 0; i < NUM_SOCCLK_DPM_LEVELS; i++)
pr_info(" .[%02d] = %d\n", i, pptable->FreqTableSocclk[i]);
pr_info("FreqTableUclk\n");
for (i = 0; i < NUM_UCLK_DPM_LEVELS; i++)
pr_info(" .[%02d] = %d\n", i, pptable->FreqTableUclk[i]);
pr_info("FreqTableFclk\n");
for (i = 0; i < NUM_FCLK_DPM_LEVELS; i++)
pr_info(" .[%02d] = %d\n", i, pptable->FreqTableFclk[i]);
pr_info("FreqTableDcefclk\n");
for (i = 0; i < NUM_DCEFCLK_DPM_LEVELS; i++)
pr_info(" .[%02d] = %d\n", i, pptable->FreqTableDcefclk[i]);
pr_info("FreqTableDispclk\n");
for (i = 0; i < NUM_DISPCLK_DPM_LEVELS; i++)
pr_info(" .[%02d] = %d\n", i, pptable->FreqTableDispclk[i]);
pr_info("FreqTablePixclk\n");
for (i = 0; i < NUM_PIXCLK_DPM_LEVELS; i++)
pr_info(" .[%02d] = %d\n", i, pptable->FreqTablePixclk[i]);
pr_info("FreqTablePhyclk\n");
for (i = 0; i < NUM_PHYCLK_DPM_LEVELS; i++)
pr_info(" .[%02d] = %d\n", i, pptable->FreqTablePhyclk[i]);
pr_info("DcModeMaxFreq[PPCLK_GFXCLK] = %d\n", pptable->DcModeMaxFreq[PPCLK_GFXCLK]);
pr_info("DcModeMaxFreq[PPCLK_VCLK] = %d\n", pptable->DcModeMaxFreq[PPCLK_VCLK]);
pr_info("DcModeMaxFreq[PPCLK_DCLK] = %d\n", pptable->DcModeMaxFreq[PPCLK_DCLK]);
pr_info("DcModeMaxFreq[PPCLK_ECLK] = %d\n", pptable->DcModeMaxFreq[PPCLK_ECLK]);
pr_info("DcModeMaxFreq[PPCLK_SOCCLK] = %d\n", pptable->DcModeMaxFreq[PPCLK_SOCCLK]);
pr_info("DcModeMaxFreq[PPCLK_UCLK] = %d\n", pptable->DcModeMaxFreq[PPCLK_UCLK]);
pr_info("DcModeMaxFreq[PPCLK_DCEFCLK] = %d\n", pptable->DcModeMaxFreq[PPCLK_DCEFCLK]);
pr_info("DcModeMaxFreq[PPCLK_DISPCLK] = %d\n", pptable->DcModeMaxFreq[PPCLK_DISPCLK]);
pr_info("DcModeMaxFreq[PPCLK_PIXCLK] = %d\n", pptable->DcModeMaxFreq[PPCLK_PIXCLK]);
pr_info("DcModeMaxFreq[PPCLK_PHYCLK] = %d\n", pptable->DcModeMaxFreq[PPCLK_PHYCLK]);
pr_info("DcModeMaxFreq[PPCLK_FCLK] = %d\n", pptable->DcModeMaxFreq[PPCLK_FCLK]);
pr_info("Padding8_Clks = %d\n", pptable->Padding8_Clks);
pr_info("Mp0clkFreq\n");
for (i = 0; i < NUM_MP0CLK_DPM_LEVELS; i++)
pr_info(" .[%d] = %d\n", i, pptable->Mp0clkFreq[i]);
pr_info("Mp0DpmVoltage\n");
for (i = 0; i < NUM_MP0CLK_DPM_LEVELS; i++)
pr_info(" .[%d] = %d\n", i, pptable->Mp0DpmVoltage[i]);
pr_info("GfxclkFidle = 0x%x\n", pptable->GfxclkFidle);
pr_info("GfxclkSlewRate = 0x%x\n", pptable->GfxclkSlewRate);
pr_info("CksEnableFreq = 0x%x\n", pptable->CksEnableFreq);
pr_info("Padding789 = 0x%x\n", pptable->Padding789);
pr_info("CksVoltageOffset[a = 0x%08x b = 0x%08x c = 0x%08x]\n",
pptable->CksVoltageOffset.a,
pptable->CksVoltageOffset.b,
pptable->CksVoltageOffset.c);
pr_info("Padding567[0] = 0x%x\n", pptable->Padding567[0]);
pr_info("Padding567[1] = 0x%x\n", pptable->Padding567[1]);
pr_info("Padding567[2] = 0x%x\n", pptable->Padding567[2]);
pr_info("Padding567[3] = 0x%x\n", pptable->Padding567[3]);
pr_info("GfxclkDsMaxFreq = %d\n", pptable->GfxclkDsMaxFreq);
pr_info("GfxclkSource = 0x%x\n", pptable->GfxclkSource);
pr_info("Padding456 = 0x%x\n", pptable->Padding456);
pr_info("LowestUclkReservedForUlv = %d\n", pptable->LowestUclkReservedForUlv);
pr_info("Padding8_Uclk[0] = 0x%x\n", pptable->Padding8_Uclk[0]);
pr_info("Padding8_Uclk[1] = 0x%x\n", pptable->Padding8_Uclk[1]);
pr_info("Padding8_Uclk[2] = 0x%x\n", pptable->Padding8_Uclk[2]);
pr_info("PcieGenSpeed\n");
for (i = 0; i < NUM_LINK_LEVELS; i++)
pr_info(" .[%d] = %d\n", i, pptable->PcieGenSpeed[i]);
pr_info("PcieLaneCount\n");
for (i = 0; i < NUM_LINK_LEVELS; i++)
pr_info(" .[%d] = %d\n", i, pptable->PcieLaneCount[i]);
pr_info("LclkFreq\n");
for (i = 0; i < NUM_LINK_LEVELS; i++)
pr_info(" .[%d] = %d\n", i, pptable->LclkFreq[i]);
pr_info("EnableTdpm = %d\n", pptable->EnableTdpm);
pr_info("TdpmHighHystTemperature = %d\n", pptable->TdpmHighHystTemperature);
pr_info("TdpmLowHystTemperature = %d\n", pptable->TdpmLowHystTemperature);
pr_info("GfxclkFreqHighTempLimit = %d\n", pptable->GfxclkFreqHighTempLimit);
pr_info("FanStopTemp = %d\n", pptable->FanStopTemp);
pr_info("FanStartTemp = %d\n", pptable->FanStartTemp);
pr_info("FanGainEdge = %d\n", pptable->FanGainEdge);
pr_info("FanGainHotspot = %d\n", pptable->FanGainHotspot);
pr_info("FanGainLiquid = %d\n", pptable->FanGainLiquid);
pr_info("FanGainVrGfx = %d\n", pptable->FanGainVrGfx);
pr_info("FanGainVrSoc = %d\n", pptable->FanGainVrSoc);
pr_info("FanGainPlx = %d\n", pptable->FanGainPlx);
pr_info("FanGainHbm = %d\n", pptable->FanGainHbm);
pr_info("FanPwmMin = %d\n", pptable->FanPwmMin);
pr_info("FanAcousticLimitRpm = %d\n", pptable->FanAcousticLimitRpm);
pr_info("FanThrottlingRpm = %d\n", pptable->FanThrottlingRpm);
pr_info("FanMaximumRpm = %d\n", pptable->FanMaximumRpm);
pr_info("FanTargetTemperature = %d\n", pptable->FanTargetTemperature);
pr_info("FanTargetGfxclk = %d\n", pptable->FanTargetGfxclk);
pr_info("FanZeroRpmEnable = %d\n", pptable->FanZeroRpmEnable);
pr_info("FanTachEdgePerRev = %d\n", pptable->FanTachEdgePerRev);
pr_info("FuzzyFan_ErrorSetDelta = %d\n", pptable->FuzzyFan_ErrorSetDelta);
pr_info("FuzzyFan_ErrorRateSetDelta = %d\n", pptable->FuzzyFan_ErrorRateSetDelta);
pr_info("FuzzyFan_PwmSetDelta = %d\n", pptable->FuzzyFan_PwmSetDelta);
pr_info("FuzzyFan_Reserved = %d\n", pptable->FuzzyFan_Reserved);
pr_info("OverrideAvfsGb[AVFS_VOLTAGE_GFX] = 0x%x\n", pptable->OverrideAvfsGb[AVFS_VOLTAGE_GFX]);
pr_info("OverrideAvfsGb[AVFS_VOLTAGE_SOC] = 0x%x\n", pptable->OverrideAvfsGb[AVFS_VOLTAGE_SOC]);
pr_info("Padding8_Avfs[0] = %d\n", pptable->Padding8_Avfs[0]);
pr_info("Padding8_Avfs[1] = %d\n", pptable->Padding8_Avfs[1]);
pr_info("qAvfsGb[AVFS_VOLTAGE_GFX]{a = 0x%x b = 0x%x c = 0x%x}\n",
pptable->qAvfsGb[AVFS_VOLTAGE_GFX].a,
pptable->qAvfsGb[AVFS_VOLTAGE_GFX].b,
pptable->qAvfsGb[AVFS_VOLTAGE_GFX].c);
pr_info("qAvfsGb[AVFS_VOLTAGE_SOC]{a = 0x%x b = 0x%x c = 0x%x}\n",
pptable->qAvfsGb[AVFS_VOLTAGE_SOC].a,
pptable->qAvfsGb[AVFS_VOLTAGE_SOC].b,
pptable->qAvfsGb[AVFS_VOLTAGE_SOC].c);
pr_info("dBtcGbGfxCksOn{a = 0x%x b = 0x%x c = 0x%x}\n",
pptable->dBtcGbGfxCksOn.a,
pptable->dBtcGbGfxCksOn.b,
pptable->dBtcGbGfxCksOn.c);
pr_info("dBtcGbGfxCksOff{a = 0x%x b = 0x%x c = 0x%x}\n",
pptable->dBtcGbGfxCksOff.a,
pptable->dBtcGbGfxCksOff.b,
pptable->dBtcGbGfxCksOff.c);
pr_info("dBtcGbGfxAfll{a = 0x%x b = 0x%x c = 0x%x}\n",
pptable->dBtcGbGfxAfll.a,
pptable->dBtcGbGfxAfll.b,
pptable->dBtcGbGfxAfll.c);
pr_info("dBtcGbSoc{a = 0x%x b = 0x%x c = 0x%x}\n",
pptable->dBtcGbSoc.a,
pptable->dBtcGbSoc.b,
pptable->dBtcGbSoc.c);
pr_info("qAgingGb[AVFS_VOLTAGE_GFX]{m = 0x%x b = 0x%x}\n",
pptable->qAgingGb[AVFS_VOLTAGE_GFX].m,
pptable->qAgingGb[AVFS_VOLTAGE_GFX].b);
pr_info("qAgingGb[AVFS_VOLTAGE_SOC]{m = 0x%x b = 0x%x}\n",
pptable->qAgingGb[AVFS_VOLTAGE_SOC].m,
pptable->qAgingGb[AVFS_VOLTAGE_SOC].b);
pr_info("qStaticVoltageOffset[AVFS_VOLTAGE_GFX]{a = 0x%x b = 0x%x c = 0x%x}\n",
pptable->qStaticVoltageOffset[AVFS_VOLTAGE_GFX].a,
pptable->qStaticVoltageOffset[AVFS_VOLTAGE_GFX].b,
pptable->qStaticVoltageOffset[AVFS_VOLTAGE_GFX].c);
pr_info("qStaticVoltageOffset[AVFS_VOLTAGE_SOC]{a = 0x%x b = 0x%x c = 0x%x}\n",
pptable->qStaticVoltageOffset[AVFS_VOLTAGE_SOC].a,
pptable->qStaticVoltageOffset[AVFS_VOLTAGE_SOC].b,
pptable->qStaticVoltageOffset[AVFS_VOLTAGE_SOC].c);
pr_info("DcTol[AVFS_VOLTAGE_GFX] = 0x%x\n", pptable->DcTol[AVFS_VOLTAGE_GFX]);
pr_info("DcTol[AVFS_VOLTAGE_SOC] = 0x%x\n", pptable->DcTol[AVFS_VOLTAGE_SOC]);
pr_info("DcBtcEnabled[AVFS_VOLTAGE_GFX] = 0x%x\n", pptable->DcBtcEnabled[AVFS_VOLTAGE_GFX]);
pr_info("DcBtcEnabled[AVFS_VOLTAGE_SOC] = 0x%x\n", pptable->DcBtcEnabled[AVFS_VOLTAGE_SOC]);
pr_info("Padding8_GfxBtc[0] = 0x%x\n", pptable->Padding8_GfxBtc[0]);
pr_info("Padding8_GfxBtc[1] = 0x%x\n", pptable->Padding8_GfxBtc[1]);
pr_info("DcBtcMin[AVFS_VOLTAGE_GFX] = 0x%x\n", pptable->DcBtcMin[AVFS_VOLTAGE_GFX]);
pr_info("DcBtcMin[AVFS_VOLTAGE_SOC] = 0x%x\n", pptable->DcBtcMin[AVFS_VOLTAGE_SOC]);
pr_info("DcBtcMax[AVFS_VOLTAGE_GFX] = 0x%x\n", pptable->DcBtcMax[AVFS_VOLTAGE_GFX]);
pr_info("DcBtcMax[AVFS_VOLTAGE_SOC] = 0x%x\n", pptable->DcBtcMax[AVFS_VOLTAGE_SOC]);
pr_info("XgmiLinkSpeed\n");
for (i = 0; i < NUM_XGMI_LEVELS; i++)
pr_info(" .[%d] = %d\n", i, pptable->XgmiLinkSpeed[i]);
pr_info("XgmiLinkWidth\n");
for (i = 0; i < NUM_XGMI_LEVELS; i++)
pr_info(" .[%d] = %d\n", i, pptable->XgmiLinkWidth[i]);
pr_info("XgmiFclkFreq\n");
for (i = 0; i < NUM_XGMI_LEVELS; i++)
pr_info(" .[%d] = %d\n", i, pptable->XgmiFclkFreq[i]);
pr_info("XgmiUclkFreq\n");
for (i = 0; i < NUM_XGMI_LEVELS; i++)
pr_info(" .[%d] = %d\n", i, pptable->XgmiUclkFreq[i]);
pr_info("XgmiSocclkFreq\n");
for (i = 0; i < NUM_XGMI_LEVELS; i++)
pr_info(" .[%d] = %d\n", i, pptable->XgmiSocclkFreq[i]);
pr_info("XgmiSocVoltage\n");
for (i = 0; i < NUM_XGMI_LEVELS; i++)
pr_info(" .[%d] = %d\n", i, pptable->XgmiSocVoltage[i]);
pr_info("DebugOverrides = 0x%x\n", pptable->DebugOverrides);
pr_info("ReservedEquation0{a = 0x%x b = 0x%x c = 0x%x}\n",
pptable->ReservedEquation0.a,
pptable->ReservedEquation0.b,
pptable->ReservedEquation0.c);
pr_info("ReservedEquation1{a = 0x%x b = 0x%x c = 0x%x}\n",
pptable->ReservedEquation1.a,
pptable->ReservedEquation1.b,
pptable->ReservedEquation1.c);
pr_info("ReservedEquation2{a = 0x%x b = 0x%x c = 0x%x}\n",
pptable->ReservedEquation2.a,
pptable->ReservedEquation2.b,
pptable->ReservedEquation2.c);
pr_info("ReservedEquation3{a = 0x%x b = 0x%x c = 0x%x}\n",
pptable->ReservedEquation3.a,
pptable->ReservedEquation3.b,
pptable->ReservedEquation3.c);
pr_info("MinVoltageUlvGfx = %d\n", pptable->MinVoltageUlvGfx);
pr_info("MinVoltageUlvSoc = %d\n", pptable->MinVoltageUlvSoc);
pr_info("MGpuFanBoostLimitRpm = %d\n", pptable->MGpuFanBoostLimitRpm);
pr_info("padding16_Fan = %d\n", pptable->padding16_Fan);
pr_info("FanGainVrMem0 = %d\n", pptable->FanGainVrMem0);
pr_info("FanGainVrMem0 = %d\n", pptable->FanGainVrMem0);
pr_info("DcBtcGb[AVFS_VOLTAGE_GFX] = 0x%x\n", pptable->DcBtcGb[AVFS_VOLTAGE_GFX]);
pr_info("DcBtcGb[AVFS_VOLTAGE_SOC] = 0x%x\n", pptable->DcBtcGb[AVFS_VOLTAGE_SOC]);
for (i = 0; i < 11; i++)
pr_info("Reserved[%d] = 0x%x\n", i, pptable->Reserved[i]);
for (i = 0; i < 3; i++)
pr_info("Padding32[%d] = 0x%x\n", i, pptable->Padding32[i]);
pr_info("MaxVoltageStepGfx = 0x%x\n", pptable->MaxVoltageStepGfx);
pr_info("MaxVoltageStepSoc = 0x%x\n", pptable->MaxVoltageStepSoc);
pr_info("VddGfxVrMapping = 0x%x\n", pptable->VddGfxVrMapping);
pr_info("VddSocVrMapping = 0x%x\n", pptable->VddSocVrMapping);
pr_info("VddMem0VrMapping = 0x%x\n", pptable->VddMem0VrMapping);
pr_info("VddMem1VrMapping = 0x%x\n", pptable->VddMem1VrMapping);
pr_info("GfxUlvPhaseSheddingMask = 0x%x\n", pptable->GfxUlvPhaseSheddingMask);
pr_info("SocUlvPhaseSheddingMask = 0x%x\n", pptable->SocUlvPhaseSheddingMask);
pr_info("ExternalSensorPresent = 0x%x\n", pptable->ExternalSensorPresent);
pr_info("Padding8_V = 0x%x\n", pptable->Padding8_V);
pr_info("GfxMaxCurrent = 0x%x\n", pptable->GfxMaxCurrent);
pr_info("GfxOffset = 0x%x\n", pptable->GfxOffset);
pr_info("Padding_TelemetryGfx = 0x%x\n", pptable->Padding_TelemetryGfx);
pr_info("SocMaxCurrent = 0x%x\n", pptable->SocMaxCurrent);
pr_info("SocOffset = 0x%x\n", pptable->SocOffset);
pr_info("Padding_TelemetrySoc = 0x%x\n", pptable->Padding_TelemetrySoc);
pr_info("Mem0MaxCurrent = 0x%x\n", pptable->Mem0MaxCurrent);
pr_info("Mem0Offset = 0x%x\n", pptable->Mem0Offset);
pr_info("Padding_TelemetryMem0 = 0x%x\n", pptable->Padding_TelemetryMem0);
pr_info("Mem1MaxCurrent = 0x%x\n", pptable->Mem1MaxCurrent);
pr_info("Mem1Offset = 0x%x\n", pptable->Mem1Offset);
pr_info("Padding_TelemetryMem1 = 0x%x\n", pptable->Padding_TelemetryMem1);
pr_info("AcDcGpio = %d\n", pptable->AcDcGpio);
pr_info("AcDcPolarity = %d\n", pptable->AcDcPolarity);
pr_info("VR0HotGpio = %d\n", pptable->VR0HotGpio);
pr_info("VR0HotPolarity = %d\n", pptable->VR0HotPolarity);
pr_info("VR1HotGpio = %d\n", pptable->VR1HotGpio);
pr_info("VR1HotPolarity = %d\n", pptable->VR1HotPolarity);
pr_info("Padding1 = 0x%x\n", pptable->Padding1);
pr_info("Padding2 = 0x%x\n", pptable->Padding2);
pr_info("LedPin0 = %d\n", pptable->LedPin0);
pr_info("LedPin1 = %d\n", pptable->LedPin1);
pr_info("LedPin2 = %d\n", pptable->LedPin2);
pr_info("padding8_4 = 0x%x\n", pptable->padding8_4);
pr_info("PllGfxclkSpreadEnabled = %d\n", pptable->PllGfxclkSpreadEnabled);
pr_info("PllGfxclkSpreadPercent = %d\n", pptable->PllGfxclkSpreadPercent);
pr_info("PllGfxclkSpreadFreq = %d\n", pptable->PllGfxclkSpreadFreq);
pr_info("UclkSpreadEnabled = %d\n", pptable->UclkSpreadEnabled);
pr_info("UclkSpreadPercent = %d\n", pptable->UclkSpreadPercent);
pr_info("UclkSpreadFreq = %d\n", pptable->UclkSpreadFreq);
pr_info("FclkSpreadEnabled = %d\n", pptable->FclkSpreadEnabled);
pr_info("FclkSpreadPercent = %d\n", pptable->FclkSpreadPercent);
pr_info("FclkSpreadFreq = %d\n", pptable->FclkSpreadFreq);
pr_info("FllGfxclkSpreadEnabled = %d\n", pptable->FllGfxclkSpreadEnabled);
pr_info("FllGfxclkSpreadPercent = %d\n", pptable->FllGfxclkSpreadPercent);
pr_info("FllGfxclkSpreadFreq = %d\n", pptable->FllGfxclkSpreadFreq);
for (i = 0; i < I2C_CONTROLLER_NAME_COUNT; i++) {
pr_info("I2cControllers[%d]:\n", i);
pr_info(" .Enabled = %d\n",
pptable->I2cControllers[i].Enabled);
pr_info(" .SlaveAddress = 0x%x\n",
pptable->I2cControllers[i].SlaveAddress);
pr_info(" .ControllerPort = %d\n",
pptable->I2cControllers[i].ControllerPort);
pr_info(" .ControllerName = %d\n",
pptable->I2cControllers[i].ControllerName);
pr_info(" .ThermalThrottler = %d\n",
pptable->I2cControllers[i].ThermalThrottler);
pr_info(" .I2cProtocol = %d\n",
pptable->I2cControllers[i].I2cProtocol);
pr_info(" .I2cSpeed = %d\n",
pptable->I2cControllers[i].I2cSpeed);
}
for (i = 0; i < 10; i++)
pr_info("BoardReserved[%d] = 0x%x\n", i, pptable->BoardReserved[i]);
for (i = 0; i < 8; i++)
pr_info("MmHubPadding[%d] = 0x%x\n", i, pptable->MmHubPadding[i]);
}
#endif
static int check_powerplay_tables(
struct pp_hwmgr *hwmgr,
const ATOM_Vega20_POWERPLAYTABLE *powerplay_table)
{
PP_ASSERT_WITH_CODE((powerplay_table->sHeader.format_revision >=
ATOM_VEGA20_TABLE_REVISION_VEGA20),
"Unsupported PPTable format!", return -1);
PP_ASSERT_WITH_CODE(powerplay_table->sHeader.structuresize > 0,
"Invalid PowerPlay Table!", return -1);
if (powerplay_table->smcPPTable.Version != PPTABLE_V20_SMU_VERSION) {
pr_info("Unmatch PPTable version: "
"pptable from VBIOS is V%d while driver supported is V%d!",
powerplay_table->smcPPTable.Version,
PPTABLE_V20_SMU_VERSION);
return -EINVAL;
}
//dump_pptable(&powerplay_table->smcPPTable);
return 0;
}
static int set_platform_caps(struct pp_hwmgr *hwmgr, uint32_t powerplay_caps)
{
set_hw_cap(
hwmgr,
0 != (powerplay_caps & ATOM_VEGA20_PP_PLATFORM_CAP_POWERPLAY),
PHM_PlatformCaps_PowerPlaySupport);
set_hw_cap(
hwmgr,
0 != (powerplay_caps & ATOM_VEGA20_PP_PLATFORM_CAP_SBIOSPOWERSOURCE),
PHM_PlatformCaps_BiosPowerSourceControl);
set_hw_cap(
hwmgr,
0 != (powerplay_caps & ATOM_VEGA20_PP_PLATFORM_CAP_BACO),
PHM_PlatformCaps_BACO);
set_hw_cap(
hwmgr,
0 != (powerplay_caps & ATOM_VEGA20_PP_PLATFORM_CAP_BAMACO),
PHM_PlatformCaps_BAMACO);
return 0;
}
static int copy_overdrive_feature_capabilities_array(
struct pp_hwmgr *hwmgr,
uint8_t **pptable_info_array,
const uint8_t *pptable_array,
uint8_t od_feature_count)
{
uint32_t array_size, i;
uint8_t *table;
bool od_supported = false;
array_size = sizeof(uint8_t) * od_feature_count;
table = kzalloc(array_size, GFP_KERNEL);
if (NULL == table)
return -ENOMEM;
for (i = 0; i < od_feature_count; i++) {
table[i] = le32_to_cpu(pptable_array[i]);
if (table[i])
od_supported = true;
}
*pptable_info_array = table;
if (od_supported)
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_ACOverdriveSupport);
return 0;
}
static int append_vbios_pptable(struct pp_hwmgr *hwmgr, PPTable_t *ppsmc_pptable)
{
struct atom_smc_dpm_info_v4_4 *smc_dpm_table;
int index = GetIndexIntoMasterDataTable(smc_dpm_info);
int i;
PP_ASSERT_WITH_CODE(
smc_dpm_table = smu_atom_get_data_table(hwmgr->adev, index, NULL, NULL, NULL),
"[appendVbiosPPTable] Failed to retrieve Smc Dpm Table from VBIOS!",
return -1);
ppsmc_pptable->MaxVoltageStepGfx = smc_dpm_table->maxvoltagestepgfx;
ppsmc_pptable->MaxVoltageStepSoc = smc_dpm_table->maxvoltagestepsoc;
ppsmc_pptable->VddGfxVrMapping = smc_dpm_table->vddgfxvrmapping;
ppsmc_pptable->VddSocVrMapping = smc_dpm_table->vddsocvrmapping;
ppsmc_pptable->VddMem0VrMapping = smc_dpm_table->vddmem0vrmapping;
ppsmc_pptable->VddMem1VrMapping = smc_dpm_table->vddmem1vrmapping;
ppsmc_pptable->GfxUlvPhaseSheddingMask = smc_dpm_table->gfxulvphasesheddingmask;
ppsmc_pptable->SocUlvPhaseSheddingMask = smc_dpm_table->soculvphasesheddingmask;
ppsmc_pptable->ExternalSensorPresent = smc_dpm_table->externalsensorpresent;
ppsmc_pptable->GfxMaxCurrent = smc_dpm_table->gfxmaxcurrent;
ppsmc_pptable->GfxOffset = smc_dpm_table->gfxoffset;
ppsmc_pptable->Padding_TelemetryGfx = smc_dpm_table->padding_telemetrygfx;
ppsmc_pptable->SocMaxCurrent = smc_dpm_table->socmaxcurrent;
ppsmc_pptable->SocOffset = smc_dpm_table->socoffset;
ppsmc_pptable->Padding_TelemetrySoc = smc_dpm_table->padding_telemetrysoc;
ppsmc_pptable->Mem0MaxCurrent = smc_dpm_table->mem0maxcurrent;
ppsmc_pptable->Mem0Offset = smc_dpm_table->mem0offset;
ppsmc_pptable->Padding_TelemetryMem0 = smc_dpm_table->padding_telemetrymem0;
ppsmc_pptable->Mem1MaxCurrent = smc_dpm_table->mem1maxcurrent;
ppsmc_pptable->Mem1Offset = smc_dpm_table->mem1offset;
ppsmc_pptable->Padding_TelemetryMem1 = smc_dpm_table->padding_telemetrymem1;
ppsmc_pptable->AcDcGpio = smc_dpm_table->acdcgpio;
ppsmc_pptable->AcDcPolarity = smc_dpm_table->acdcpolarity;
ppsmc_pptable->VR0HotGpio = smc_dpm_table->vr0hotgpio;
ppsmc_pptable->VR0HotPolarity = smc_dpm_table->vr0hotpolarity;
ppsmc_pptable->VR1HotGpio = smc_dpm_table->vr1hotgpio;
ppsmc_pptable->VR1HotPolarity = smc_dpm_table->vr1hotpolarity;
ppsmc_pptable->Padding1 = smc_dpm_table->padding1;
ppsmc_pptable->Padding2 = smc_dpm_table->padding2;
ppsmc_pptable->LedPin0 = smc_dpm_table->ledpin0;
ppsmc_pptable->LedPin1 = smc_dpm_table->ledpin1;
ppsmc_pptable->LedPin2 = smc_dpm_table->ledpin2;
ppsmc_pptable->PllGfxclkSpreadEnabled = smc_dpm_table->pllgfxclkspreadenabled;
ppsmc_pptable->PllGfxclkSpreadPercent = smc_dpm_table->pllgfxclkspreadpercent;
ppsmc_pptable->PllGfxclkSpreadFreq = smc_dpm_table->pllgfxclkspreadfreq;
ppsmc_pptable->UclkSpreadEnabled = 0;
ppsmc_pptable->UclkSpreadPercent = smc_dpm_table->uclkspreadpercent;
ppsmc_pptable->UclkSpreadFreq = smc_dpm_table->uclkspreadfreq;
ppsmc_pptable->FclkSpreadEnabled = smc_dpm_table->fclkspreadenabled;
ppsmc_pptable->FclkSpreadPercent = smc_dpm_table->fclkspreadpercent;
ppsmc_pptable->FclkSpreadFreq = smc_dpm_table->fclkspreadfreq;
ppsmc_pptable->FllGfxclkSpreadEnabled = smc_dpm_table->fllgfxclkspreadenabled;
ppsmc_pptable->FllGfxclkSpreadPercent = smc_dpm_table->fllgfxclkspreadpercent;
ppsmc_pptable->FllGfxclkSpreadFreq = smc_dpm_table->fllgfxclkspreadfreq;
for (i = 0; i < I2C_CONTROLLER_NAME_COUNT; i++) {
ppsmc_pptable->I2cControllers[i].Enabled =
smc_dpm_table->i2ccontrollers[i].enabled;
ppsmc_pptable->I2cControllers[i].SlaveAddress =
smc_dpm_table->i2ccontrollers[i].slaveaddress;
ppsmc_pptable->I2cControllers[i].ControllerPort =
smc_dpm_table->i2ccontrollers[i].controllerport;
ppsmc_pptable->I2cControllers[i].ThermalThrottler =
smc_dpm_table->i2ccontrollers[i].thermalthrottler;
ppsmc_pptable->I2cControllers[i].I2cProtocol =
smc_dpm_table->i2ccontrollers[i].i2cprotocol;
ppsmc_pptable->I2cControllers[i].I2cSpeed =
smc_dpm_table->i2ccontrollers[i].i2cspeed;
}
return 0;
}
static int override_powerplay_table_fantargettemperature(struct pp_hwmgr *hwmgr)
{
struct phm_ppt_v3_information *pptable_information =
(struct phm_ppt_v3_information *)hwmgr->pptable;
PPTable_t *ppsmc_pptable = (PPTable_t *)(pptable_information->smc_pptable);
ppsmc_pptable->FanTargetTemperature = VEGA20_FAN_TARGET_TEMPERATURE_OVERRIDE;
return 0;
}
#define VEGA20_ENGINECLOCK_HARDMAX 198000
static int init_powerplay_table_information(
struct pp_hwmgr *hwmgr,
const ATOM_Vega20_POWERPLAYTABLE *powerplay_table)
{
struct phm_ppt_v3_information *pptable_information =
(struct phm_ppt_v3_information *)hwmgr->pptable;
uint32_t disable_power_control = 0;
uint32_t od_feature_count, od_setting_count, power_saving_clock_count;
int result;
hwmgr->thermal_controller.ucType = powerplay_table->ucThermalControllerType;
pptable_information->uc_thermal_controller_type = powerplay_table->ucThermalControllerType;
hwmgr->thermal_controller.fanInfo.ulMinRPM = 0;
hwmgr->thermal_controller.fanInfo.ulMaxRPM = powerplay_table->smcPPTable.FanMaximumRpm;
set_hw_cap(hwmgr,
ATOM_VEGA20_PP_THERMALCONTROLLER_NONE != hwmgr->thermal_controller.ucType,
PHM_PlatformCaps_ThermalController);
phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl);
if (powerplay_table->OverDrive8Table.ucODTableRevision == 1) {
od_feature_count =
(le32_to_cpu(powerplay_table->OverDrive8Table.ODFeatureCount) >
ATOM_VEGA20_ODFEATURE_COUNT) ?
ATOM_VEGA20_ODFEATURE_COUNT :
le32_to_cpu(powerplay_table->OverDrive8Table.ODFeatureCount);
od_setting_count =
(le32_to_cpu(powerplay_table->OverDrive8Table.ODSettingCount) >
ATOM_VEGA20_ODSETTING_COUNT) ?
ATOM_VEGA20_ODSETTING_COUNT :
le32_to_cpu(powerplay_table->OverDrive8Table.ODSettingCount);
copy_overdrive_feature_capabilities_array(hwmgr,
&pptable_information->od_feature_capabilities,
powerplay_table->OverDrive8Table.ODFeatureCapabilities,
od_feature_count);
phm_copy_overdrive_settings_limits_array(hwmgr,
&pptable_information->od_settings_max,
powerplay_table->OverDrive8Table.ODSettingsMax,
od_setting_count);
phm_copy_overdrive_settings_limits_array(hwmgr,
&pptable_information->od_settings_min,
powerplay_table->OverDrive8Table.ODSettingsMin,
od_setting_count);
}
pptable_information->us_small_power_limit1 = le16_to_cpu(powerplay_table->usSmallPowerLimit1);
pptable_information->us_small_power_limit2 = le16_to_cpu(powerplay_table->usSmallPowerLimit2);
pptable_information->us_boost_power_limit = le16_to_cpu(powerplay_table->usBoostPowerLimit);
pptable_information->us_od_turbo_power_limit = le16_to_cpu(powerplay_table->usODTurboPowerLimit);
pptable_information->us_od_powersave_power_limit = le16_to_cpu(powerplay_table->usODPowerSavePowerLimit);
pptable_information->us_software_shutdown_temp = le16_to_cpu(powerplay_table->usSoftwareShutdownTemp);
hwmgr->platform_descriptor.TDPODLimit = le32_to_cpu(powerplay_table->OverDrive8Table.ODSettingsMax[ATOM_VEGA20_ODSETTING_POWERPERCENTAGE]);
disable_power_control = 0;
if (!disable_power_control && hwmgr->platform_descriptor.TDPODLimit)
/* enable TDP overdrive (PowerControl) feature as well if supported */
phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PowerControl);
if (powerplay_table->PowerSavingClockTable.ucTableRevision == 1) {
power_saving_clock_count =
(le32_to_cpu(powerplay_table->PowerSavingClockTable.PowerSavingClockCount) >=
ATOM_VEGA20_PPCLOCK_COUNT) ?
ATOM_VEGA20_PPCLOCK_COUNT :
le32_to_cpu(powerplay_table->PowerSavingClockTable.PowerSavingClockCount);
phm_copy_clock_limits_array(hwmgr,
&pptable_information->power_saving_clock_max,
powerplay_table->PowerSavingClockTable.PowerSavingClockMax,
power_saving_clock_count);
phm_copy_clock_limits_array(hwmgr,
&pptable_information->power_saving_clock_min,
powerplay_table->PowerSavingClockTable.PowerSavingClockMin,
power_saving_clock_count);
}
pptable_information->smc_pptable = kmemdup(&(powerplay_table->smcPPTable),
sizeof(PPTable_t),
GFP_KERNEL);
if (pptable_information->smc_pptable == NULL)
return -ENOMEM;
result = append_vbios_pptable(hwmgr, (pptable_information->smc_pptable));
if (result)
return result;
result = override_powerplay_table_fantargettemperature(hwmgr);
return result;
}
static int vega20_pp_tables_initialize(struct pp_hwmgr *hwmgr)
{
int result = 0;
const ATOM_Vega20_POWERPLAYTABLE *powerplay_table;
hwmgr->pptable = kzalloc(sizeof(struct phm_ppt_v3_information), GFP_KERNEL);
PP_ASSERT_WITH_CODE((hwmgr->pptable != NULL),
"Failed to allocate hwmgr->pptable!", return -ENOMEM);
powerplay_table = get_powerplay_table(hwmgr);
PP_ASSERT_WITH_CODE((powerplay_table != NULL),
"Missing PowerPlay Table!", return -1);
result = check_powerplay_tables(hwmgr, powerplay_table);
PP_ASSERT_WITH_CODE((result == 0),
"check_powerplay_tables failed", return result);
result = set_platform_caps(hwmgr,
le32_to_cpu(powerplay_table->ulPlatformCaps));
PP_ASSERT_WITH_CODE((result == 0),
"set_platform_caps failed", return result);
result = init_powerplay_table_information(hwmgr, powerplay_table);
PP_ASSERT_WITH_CODE((result == 0),
"init_powerplay_table_information failed", return result);
return result;
}
static int vega20_pp_tables_uninitialize(struct pp_hwmgr *hwmgr)
{
struct phm_ppt_v3_information *pp_table_info =
(struct phm_ppt_v3_information *)(hwmgr->pptable);
kfree(pp_table_info->power_saving_clock_max);
pp_table_info->power_saving_clock_max = NULL;
kfree(pp_table_info->power_saving_clock_min);
pp_table_info->power_saving_clock_min = NULL;
kfree(pp_table_info->od_feature_capabilities);
pp_table_info->od_feature_capabilities = NULL;
kfree(pp_table_info->od_settings_max);
pp_table_info->od_settings_max = NULL;
kfree(pp_table_info->od_settings_min);
pp_table_info->od_settings_min = NULL;
kfree(pp_table_info->smc_pptable);
pp_table_info->smc_pptable = NULL;
kfree(hwmgr->pptable);
hwmgr->pptable = NULL;
return 0;
}
const struct pp_table_func vega20_pptable_funcs = {
.pptable_init = vega20_pp_tables_initialize,
.pptable_fini = vega20_pp_tables_uninitialize,
};

View File

@@ -0,0 +1,31 @@
/*
* Copyright 2018 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.
*
*/
#ifndef VEGA20_PROCESSPPTABLES_H
#define VEGA20_PROCESSPPTABLES_H
#include "hwmgr.h"
extern const struct pp_table_func vega20_pptable_funcs;
#endif

View File

@@ -0,0 +1,358 @@
/*
* Copyright 2018 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 "vega20_thermal.h"
#include "vega20_hwmgr.h"
#include "vega20_smumgr.h"
#include "vega20_ppsmc.h"
#include "vega20_inc.h"
#include "soc15_common.h"
#include "pp_debug.h"
static int vega20_disable_fan_control_feature(struct pp_hwmgr *hwmgr)
{
struct vega20_hwmgr *data = hwmgr->backend;
int ret = 0;
if (data->smu_features[GNLD_FAN_CONTROL].supported) {
ret = vega20_enable_smc_features(
hwmgr, false,
data->smu_features[GNLD_FAN_CONTROL].
smu_feature_bitmap);
PP_ASSERT_WITH_CODE(!ret,
"Disable FAN CONTROL feature Failed!",
return ret);
data->smu_features[GNLD_FAN_CONTROL].enabled = false;
}
return ret;
}
int vega20_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr)
{
struct vega20_hwmgr *data = hwmgr->backend;
if (data->smu_features[GNLD_FAN_CONTROL].supported)
return vega20_disable_fan_control_feature(hwmgr);
return 0;
}
static int vega20_enable_fan_control_feature(struct pp_hwmgr *hwmgr)
{
struct vega20_hwmgr *data = hwmgr->backend;
int ret = 0;
if (data->smu_features[GNLD_FAN_CONTROL].supported) {
ret = vega20_enable_smc_features(
hwmgr, true,
data->smu_features[GNLD_FAN_CONTROL].
smu_feature_bitmap);
PP_ASSERT_WITH_CODE(!ret,
"Enable FAN CONTROL feature Failed!",
return ret);
data->smu_features[GNLD_FAN_CONTROL].enabled = true;
}
return ret;
}
int vega20_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr)
{
struct vega20_hwmgr *data = hwmgr->backend;
if (data->smu_features[GNLD_FAN_CONTROL].supported)
return vega20_enable_fan_control_feature(hwmgr);
return 0;
}
static int vega20_fan_ctrl_set_static_mode(struct pp_hwmgr *hwmgr, uint32_t mode)
{
struct amdgpu_device *adev = hwmgr->adev;
WREG32_SOC15(THM, 0, mmCG_FDO_CTRL2,
REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL2),
CG_FDO_CTRL2, TMIN, 0));
WREG32_SOC15(THM, 0, mmCG_FDO_CTRL2,
REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL2),
CG_FDO_CTRL2, FDO_PWM_MODE, mode));
return 0;
}
static int vega20_get_current_rpm(struct pp_hwmgr *hwmgr, uint32_t *current_rpm)
{
int ret = 0;
PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc(hwmgr,
PPSMC_MSG_GetCurrentRpm,
current_rpm)) == 0,
"Attempt to get current RPM from SMC Failed!",
return ret);
return 0;
}
int vega20_fan_ctrl_get_fan_speed_percent(struct pp_hwmgr *hwmgr,
uint32_t *speed)
{
struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
PPTable_t *pp_table = &(data->smc_state_table.pp_table);
uint32_t current_rpm, percent = 0;
int ret = 0;
ret = vega20_get_current_rpm(hwmgr, &current_rpm);
if (ret)
return ret;
percent = current_rpm * 100 / pp_table->FanMaximumRpm;
*speed = percent > 100 ? 100 : percent;
return 0;
}
int vega20_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr,
uint32_t speed)
{
struct amdgpu_device *adev = hwmgr->adev;
uint32_t duty100;
uint32_t duty;
uint64_t tmp64;
if (speed > 100)
speed = 100;
if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl))
vega20_fan_ctrl_stop_smc_fan_control(hwmgr);
duty100 = REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL1),
CG_FDO_CTRL1, FMAX_DUTY100);
if (duty100 == 0)
return -EINVAL;
tmp64 = (uint64_t)speed * duty100;
do_div(tmp64, 100);
duty = (uint32_t)tmp64;
WREG32_SOC15(THM, 0, mmCG_FDO_CTRL0,
REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL0),
CG_FDO_CTRL0, FDO_STATIC_DUTY, duty));
return vega20_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC);
}
int vega20_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr,
struct phm_fan_speed_info *fan_speed_info)
{
memset(fan_speed_info, 0, sizeof(*fan_speed_info));
fan_speed_info->supports_percent_read = true;
fan_speed_info->supports_percent_write = true;
fan_speed_info->supports_rpm_read = true;
fan_speed_info->supports_rpm_write = true;
return 0;
}
int vega20_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t *speed)
{
*speed = 0;
return vega20_get_current_rpm(hwmgr, speed);
}
int vega20_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed)
{
struct amdgpu_device *adev = hwmgr->adev;
uint32_t tach_period, crystal_clock_freq;
int result = 0;
if (!speed)
return -EINVAL;
if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) {
result = vega20_fan_ctrl_stop_smc_fan_control(hwmgr);
if (result)
return result;
}
crystal_clock_freq = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev);
tach_period = 60 * crystal_clock_freq * 10000 / (8 * speed);
WREG32_SOC15(THM, 0, mmCG_TACH_CTRL,
REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_TACH_CTRL),
CG_TACH_CTRL, TARGET_PERIOD,
tach_period));
return vega20_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC_RPM);
}
/**
* Reads the remote temperature from the SIslands thermal controller.
*
* @param hwmgr The address of the hardware manager.
*/
int vega20_thermal_get_temperature(struct pp_hwmgr *hwmgr)
{
struct amdgpu_device *adev = hwmgr->adev;
int temp = 0;
temp = RREG32_SOC15(THM, 0, mmCG_MULT_THERMAL_STATUS);
temp = (temp & CG_MULT_THERMAL_STATUS__CTF_TEMP_MASK) >>
CG_MULT_THERMAL_STATUS__CTF_TEMP__SHIFT;
temp = temp & 0x1ff;
temp *= PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
return temp;
}
/**
* Set the requested temperature range for high and low alert signals
*
* @param hwmgr The address of the hardware manager.
* @param range Temperature range to be programmed for
* high and low alert signals
* @exception PP_Result_BadInput if the input data is not valid.
*/
static int vega20_thermal_set_temperature_range(struct pp_hwmgr *hwmgr,
struct PP_TemperatureRange *range)
{
struct phm_ppt_v3_information *pptable_information =
(struct phm_ppt_v3_information *)hwmgr->pptable;
struct amdgpu_device *adev = hwmgr->adev;
int low = VEGA20_THERMAL_MINIMUM_ALERT_TEMP;
int high = VEGA20_THERMAL_MAXIMUM_ALERT_TEMP;
uint32_t val;
/* compare them in unit celsius degree */
if (low < range->min / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)
low = range->min / PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
if (high > pptable_information->us_software_shutdown_temp)
high = pptable_information->us_software_shutdown_temp;
if (low > high)
return -EINVAL;
val = RREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL);
val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, MAX_IH_CREDIT, 5);
val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_IH_HW_ENA, 1);
val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, high);
val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, low);
val = val & (~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK);
WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL, val);
return 0;
}
/**
* Enable thermal alerts on the RV770 thermal controller.
*
* @param hwmgr The address of the hardware manager.
*/
static int vega20_thermal_enable_alert(struct pp_hwmgr *hwmgr)
{
struct amdgpu_device *adev = hwmgr->adev;
uint32_t val = 0;
val |= (1 << THM_THERMAL_INT_ENA__THERM_INTH_CLR__SHIFT);
val |= (1 << THM_THERMAL_INT_ENA__THERM_INTL_CLR__SHIFT);
val |= (1 << THM_THERMAL_INT_ENA__THERM_TRIGGER_CLR__SHIFT);
WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_ENA, val);
return 0;
}
/**
* Disable thermal alerts on the RV770 thermal controller.
* @param hwmgr The address of the hardware manager.
*/
int vega20_thermal_disable_alert(struct pp_hwmgr *hwmgr)
{
struct amdgpu_device *adev = hwmgr->adev;
WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_ENA, 0);
return 0;
}
/**
* Uninitialize the thermal controller.
* Currently just disables alerts.
* @param hwmgr The address of the hardware manager.
*/
int vega20_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr)
{
int result = vega20_thermal_disable_alert(hwmgr);
return result;
}
/**
* Set up the fan table to control the fan using the SMC.
* @param hwmgr the address of the powerplay hardware manager.
* @param pInput the pointer to input data
* @param pOutput the pointer to output data
* @param pStorage the pointer to temporary storage
* @param Result the last failure code
* @return result from set temperature range routine
*/
static int vega20_thermal_setup_fan_table(struct pp_hwmgr *hwmgr)
{
int ret;
struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
PPTable_t *table = &(data->smc_state_table.pp_table);
ret = smum_send_msg_to_smc_with_parameter(hwmgr,
PPSMC_MSG_SetFanTemperatureTarget,
(uint32_t)table->FanTargetTemperature,
NULL);
return ret;
}
int vega20_start_thermal_controller(struct pp_hwmgr *hwmgr,
struct PP_TemperatureRange *range)
{
int ret = 0;
if (range == NULL)
return -EINVAL;
ret = vega20_thermal_set_temperature_range(hwmgr, range);
if (ret)
return ret;
ret = vega20_thermal_enable_alert(hwmgr);
if (ret)
return ret;
ret = vega20_thermal_setup_fan_table(hwmgr);
return ret;
};

View File

@@ -0,0 +1,71 @@
/*
* Copyright 2018 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.
*
*/
#ifndef VEGA20_THERMAL_H
#define VEGA20_THERMAL_H
#include "hwmgr.h"
struct vega20_temperature {
uint16_t edge_temp;
uint16_t hot_spot_temp;
uint16_t hbm_temp;
uint16_t vr_soc_temp;
uint16_t vr_mem_temp;
uint16_t liquid1_temp;
uint16_t liquid2_temp;
uint16_t plx_temp;
};
#define VEGA20_THERMAL_HIGH_ALERT_MASK 0x1
#define VEGA20_THERMAL_LOW_ALERT_MASK 0x2
#define VEGA20_THERMAL_MINIMUM_TEMP_READING -256
#define VEGA20_THERMAL_MAXIMUM_TEMP_READING 255
#define VEGA20_THERMAL_MINIMUM_ALERT_TEMP 0
#define VEGA20_THERMAL_MAXIMUM_ALERT_TEMP 255
#define FDO_PWM_MODE_STATIC 1
#define FDO_PWM_MODE_STATIC_RPM 5
extern int vega20_thermal_get_temperature(struct pp_hwmgr *hwmgr);
extern int vega20_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr,
struct phm_fan_speed_info *fan_speed_info);
extern int vega20_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr,
uint32_t *speed);
extern int vega20_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr,
uint32_t speed);
extern int vega20_fan_ctrl_get_fan_speed_percent(struct pp_hwmgr *hwmgr,
uint32_t *speed);
extern int vega20_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr,
uint32_t speed);
extern int vega20_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr);
extern int vega20_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr);
extern int vega20_thermal_disable_alert(struct pp_hwmgr *hwmgr);
extern int vega20_start_thermal_controller(struct pp_hwmgr *hwmgr,
struct PP_TemperatureRange *range);
extern int vega20_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,229 @@
/*
* Copyright 2013 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.
*
*/
#ifndef __KV_DPM_H__
#define __KV_DPM_H__
#define SMU__NUM_SCLK_DPM_STATE 8
#define SMU__NUM_MCLK_DPM_LEVELS 4
#define SMU__NUM_LCLK_DPM_LEVELS 8
#define SMU__NUM_PCIE_DPM_LEVELS 0 /* ??? */
#include "smu7_fusion.h"
#include "ppsmc.h"
#define SUMO_MAX_HARDWARE_POWERLEVELS 5
#define SUMO_MAX_NUMBER_VOLTAGES 4
struct sumo_vid_mapping_entry {
u16 vid_2bit;
u16 vid_7bit;
};
struct sumo_vid_mapping_table {
u32 num_entries;
struct sumo_vid_mapping_entry entries[SUMO_MAX_NUMBER_VOLTAGES];
};
struct sumo_sclk_voltage_mapping_entry {
u32 sclk_frequency;
u16 vid_2bit;
u16 rsv;
};
struct sumo_sclk_voltage_mapping_table {
u32 num_max_dpm_entries;
struct sumo_sclk_voltage_mapping_entry entries[SUMO_MAX_HARDWARE_POWERLEVELS];
};
#define TRINITY_AT_DFLT 30
#define KV_NUM_NBPSTATES 4
enum kv_pt_config_reg_type {
KV_CONFIGREG_MMR = 0,
KV_CONFIGREG_SMC_IND,
KV_CONFIGREG_DIDT_IND,
KV_CONFIGREG_CACHE,
KV_CONFIGREG_MAX
};
struct kv_pt_config_reg {
u32 offset;
u32 mask;
u32 shift;
u32 value;
enum kv_pt_config_reg_type type;
};
struct kv_lcac_config_values {
u32 block_id;
u32 signal_id;
u32 t;
};
struct kv_lcac_config_reg {
u32 cntl;
u32 block_mask;
u32 block_shift;
u32 signal_mask;
u32 signal_shift;
u32 t_mask;
u32 t_shift;
u32 enable_mask;
u32 enable_shift;
};
struct kv_pl {
u32 sclk;
u8 vddc_index;
u8 ds_divider_index;
u8 ss_divider_index;
u8 allow_gnb_slow;
u8 force_nbp_state;
u8 display_wm;
u8 vce_wm;
};
struct kv_ps {
struct kv_pl levels[SUMO_MAX_HARDWARE_POWERLEVELS];
u32 num_levels;
bool need_dfs_bypass;
u8 dpm0_pg_nb_ps_lo;
u8 dpm0_pg_nb_ps_hi;
u8 dpmx_nb_ps_lo;
u8 dpmx_nb_ps_hi;
};
struct kv_sys_info {
u32 bootup_uma_clk;
u32 bootup_sclk;
u32 dentist_vco_freq;
u32 nb_dpm_enable;
u32 nbp_memory_clock[KV_NUM_NBPSTATES];
u32 nbp_n_clock[KV_NUM_NBPSTATES];
u16 bootup_nb_voltage_index;
u8 htc_tmp_lmt;
u8 htc_hyst_lmt;
struct sumo_sclk_voltage_mapping_table sclk_voltage_mapping_table;
struct sumo_vid_mapping_table vid_mapping_table;
u32 uma_channel_number;
};
struct kv_power_info {
u32 at[SUMO_MAX_HARDWARE_POWERLEVELS];
u32 voltage_drop_t;
struct kv_sys_info sys_info;
struct kv_pl boot_pl;
bool enable_nb_ps_policy;
bool disable_nb_ps3_in_battery;
bool video_start;
bool battery_state;
u32 lowest_valid;
u32 highest_valid;
u16 high_voltage_t;
bool cac_enabled;
bool bapm_enable;
/* smc offsets */
u32 sram_end;
u32 dpm_table_start;
u32 soft_regs_start;
/* dpm SMU tables */
u8 graphics_dpm_level_count;
u8 uvd_level_count;
u8 vce_level_count;
u8 acp_level_count;
u8 samu_level_count;
u16 fps_high_t;
SMU7_Fusion_GraphicsLevel graphics_level[SMU__NUM_SCLK_DPM_STATE];
SMU7_Fusion_ACPILevel acpi_level;
SMU7_Fusion_UvdLevel uvd_level[SMU7_MAX_LEVELS_UVD];
SMU7_Fusion_ExtClkLevel vce_level[SMU7_MAX_LEVELS_VCE];
SMU7_Fusion_ExtClkLevel acp_level[SMU7_MAX_LEVELS_ACP];
SMU7_Fusion_ExtClkLevel samu_level[SMU7_MAX_LEVELS_SAMU];
u8 uvd_boot_level;
u8 vce_boot_level;
u8 acp_boot_level;
u8 samu_boot_level;
u8 uvd_interval;
u8 vce_interval;
u8 acp_interval;
u8 samu_interval;
u8 graphics_boot_level;
u8 graphics_interval;
u8 graphics_therm_throttle_enable;
u8 graphics_voltage_change_enable;
u8 graphics_clk_slow_enable;
u8 graphics_clk_slow_divider;
u8 fps_low_t;
u32 low_sclk_interrupt_t;
bool uvd_power_gated;
bool vce_power_gated;
bool acp_power_gated;
bool samu_power_gated;
bool nb_dpm_enabled;
/* flags */
bool enable_didt;
bool enable_dpm;
bool enable_auto_thermal_throttling;
bool enable_nb_dpm;
/* caps */
bool caps_cac;
bool caps_power_containment;
bool caps_sq_ramping;
bool caps_db_ramping;
bool caps_td_ramping;
bool caps_tcp_ramping;
bool caps_sclk_throttle_low_notification;
bool caps_fps;
bool caps_uvd_dpm;
bool caps_uvd_pg;
bool caps_vce_pg;
bool caps_samu_pg;
bool caps_acp_pg;
bool caps_stable_p_state;
bool caps_enable_dfs_bypass;
bool caps_sclk_ds;
struct amdgpu_ps current_rps;
struct kv_ps current_ps;
struct amdgpu_ps requested_rps;
struct kv_ps requested_ps;
};
/* XXX are these ok? */
#define KV_TEMP_RANGE_MIN (90 * 1000)
#define KV_TEMP_RANGE_MAX (120 * 1000)
/* kv_smc.c */
int amdgpu_kv_notify_message_to_smu(struct amdgpu_device *adev, u32 id);
int amdgpu_kv_dpm_get_enable_mask(struct amdgpu_device *adev, u32 *enable_mask);
int amdgpu_kv_send_msg_to_smc_with_parameter(struct amdgpu_device *adev,
PPSMC_Msg msg, u32 parameter);
int amdgpu_kv_read_smc_sram_dword(struct amdgpu_device *adev, u32 smc_address,
u32 *value, u32 limit);
int amdgpu_kv_smc_dpm_enable(struct amdgpu_device *adev, bool enable);
int amdgpu_kv_smc_bapm_enable(struct amdgpu_device *adev, bool enable);
int amdgpu_kv_copy_bytes_to_smc(struct amdgpu_device *adev,
u32 smc_start_address,
const u8 *src, u32 byte_count, u32 limit);
#endif

View File

@@ -0,0 +1,218 @@
/*
* Copyright 2013 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.
*
* Authors: Alex Deucher
*/
#include "amdgpu.h"
#include "cikd.h"
#include "kv_dpm.h"
#include "smu/smu_7_0_0_d.h"
#include "smu/smu_7_0_0_sh_mask.h"
int amdgpu_kv_notify_message_to_smu(struct amdgpu_device *adev, u32 id)
{
u32 i;
u32 tmp = 0;
WREG32(mmSMC_MESSAGE_0, id & SMC_MESSAGE_0__SMC_MSG_MASK);
for (i = 0; i < adev->usec_timeout; i++) {
if ((RREG32(mmSMC_RESP_0) & SMC_RESP_0__SMC_RESP_MASK) != 0)
break;
udelay(1);
}
tmp = RREG32(mmSMC_RESP_0) & SMC_RESP_0__SMC_RESP_MASK;
if (tmp != 1) {
if (tmp == 0xFF)
return -EINVAL;
else if (tmp == 0xFE)
return -EINVAL;
}
return 0;
}
int amdgpu_kv_dpm_get_enable_mask(struct amdgpu_device *adev, u32 *enable_mask)
{
int ret;
ret = amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_SCLKDPM_GetEnabledMask);
if (ret == 0)
*enable_mask = RREG32_SMC(ixSMC_SYSCON_MSG_ARG_0);
return ret;
}
int amdgpu_kv_send_msg_to_smc_with_parameter(struct amdgpu_device *adev,
PPSMC_Msg msg, u32 parameter)
{
WREG32(mmSMC_MSG_ARG_0, parameter);
return amdgpu_kv_notify_message_to_smu(adev, msg);
}
static int kv_set_smc_sram_address(struct amdgpu_device *adev,
u32 smc_address, u32 limit)
{
if (smc_address & 3)
return -EINVAL;
if ((smc_address + 3) > limit)
return -EINVAL;
WREG32(mmSMC_IND_INDEX_0, smc_address);
WREG32_P(mmSMC_IND_ACCESS_CNTL, 0,
~SMC_IND_ACCESS_CNTL__AUTO_INCREMENT_IND_0_MASK);
return 0;
}
int amdgpu_kv_read_smc_sram_dword(struct amdgpu_device *adev, u32 smc_address,
u32 *value, u32 limit)
{
int ret;
ret = kv_set_smc_sram_address(adev, smc_address, limit);
if (ret)
return ret;
*value = RREG32(mmSMC_IND_DATA_0);
return 0;
}
int amdgpu_kv_smc_dpm_enable(struct amdgpu_device *adev, bool enable)
{
if (enable)
return amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_DPM_Enable);
else
return amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_DPM_Disable);
}
int amdgpu_kv_smc_bapm_enable(struct amdgpu_device *adev, bool enable)
{
if (enable)
return amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_EnableBAPM);
else
return amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_DisableBAPM);
}
int amdgpu_kv_copy_bytes_to_smc(struct amdgpu_device *adev,
u32 smc_start_address,
const u8 *src, u32 byte_count, u32 limit)
{
int ret;
u32 data, original_data, addr, extra_shift, t_byte, count, mask;
if ((smc_start_address + byte_count) > limit)
return -EINVAL;
addr = smc_start_address;
t_byte = addr & 3;
/* RMW for the initial bytes */
if (t_byte != 0) {
addr -= t_byte;
ret = kv_set_smc_sram_address(adev, addr, limit);
if (ret)
return ret;
original_data = RREG32(mmSMC_IND_DATA_0);
data = 0;
mask = 0;
count = 4;
while (count > 0) {
if (t_byte > 0) {
mask = (mask << 8) | 0xff;
t_byte--;
} else if (byte_count > 0) {
data = (data << 8) + *src++;
byte_count--;
mask <<= 8;
} else {
data <<= 8;
mask = (mask << 8) | 0xff;
}
count--;
}
data |= original_data & mask;
ret = kv_set_smc_sram_address(adev, addr, limit);
if (ret)
return ret;
WREG32(mmSMC_IND_DATA_0, data);
addr += 4;
}
while (byte_count >= 4) {
/* SMC address space is BE */
data = (src[0] << 24) + (src[1] << 16) + (src[2] << 8) + src[3];
ret = kv_set_smc_sram_address(adev, addr, limit);
if (ret)
return ret;
WREG32(mmSMC_IND_DATA_0, data);
src += 4;
byte_count -= 4;
addr += 4;
}
/* RMW for the final bytes */
if (byte_count > 0) {
data = 0;
ret = kv_set_smc_sram_address(adev, addr, limit);
if (ret)
return ret;
original_data = RREG32(mmSMC_IND_DATA_0);
extra_shift = 8 * (4 - byte_count);
while (byte_count > 0) {
/* SMC address space is BE */
data = (data << 8) + *src++;
byte_count--;
}
data <<= extra_shift;
data |= (original_data & ~((~0UL) << extra_shift));
ret = kv_set_smc_sram_address(adev, addr, limit);
if (ret)
return ret;
WREG32(mmSMC_IND_DATA_0, data);
}
return 0;
}

View File

@@ -0,0 +1,200 @@
/*
* Copyright 2011 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.
*
*/
#ifndef PP_SMC_H
#define PP_SMC_H
#pragma pack(push, 1)
#define PPSMC_SWSTATE_FLAG_DC 0x01
#define PPSMC_SWSTATE_FLAG_UVD 0x02
#define PPSMC_SWSTATE_FLAG_VCE 0x04
#define PPSMC_SWSTATE_FLAG_PCIE_X1 0x08
#define PPSMC_THERMAL_PROTECT_TYPE_INTERNAL 0x00
#define PPSMC_THERMAL_PROTECT_TYPE_EXTERNAL 0x01
#define PPSMC_THERMAL_PROTECT_TYPE_NONE 0xff
#define PPSMC_SYSTEMFLAG_GPIO_DC 0x01
#define PPSMC_SYSTEMFLAG_STEPVDDC 0x02
#define PPSMC_SYSTEMFLAG_GDDR5 0x04
#define PPSMC_SYSTEMFLAG_DISABLE_BABYSTEP 0x08
#define PPSMC_SYSTEMFLAG_REGULATOR_HOT 0x10
#define PPSMC_SYSTEMFLAG_REGULATOR_HOT_ANALOG 0x20
#define PPSMC_SYSTEMFLAG_REGULATOR_HOT_PROG_GPIO 0x40
#define PPSMC_EXTRAFLAGS_AC2DC_ACTION_MASK 0x07
#define PPSMC_EXTRAFLAGS_AC2DC_DONT_WAIT_FOR_VBLANK 0x08
#define PPSMC_EXTRAFLAGS_AC2DC_ACTION_GOTODPMLOWSTATE 0x00
#define PPSMC_EXTRAFLAGS_AC2DC_ACTION_GOTOINITIALSTATE 0x01
#define PPSMC_EXTRAFLAGS_AC2DC_GPIO5_POLARITY_HIGH 0x02
#define PPSMC_DISPLAY_WATERMARK_LOW 0
#define PPSMC_DISPLAY_WATERMARK_HIGH 1
#define PPSMC_STATEFLAG_AUTO_PULSE_SKIP 0x01
#define PPSMC_STATEFLAG_POWERBOOST 0x02
#define PPSMC_STATEFLAG_DEEPSLEEP_THROTTLE 0x20
#define PPSMC_STATEFLAG_DEEPSLEEP_BYPASS 0x40
#define FDO_MODE_HARDWARE 0
#define FDO_MODE_PIECE_WISE_LINEAR 1
enum FAN_CONTROL {
FAN_CONTROL_FUZZY,
FAN_CONTROL_TABLE
};
#define PPSMC_Result_OK ((uint8_t)0x01)
#define PPSMC_Result_Failed ((uint8_t)0xFF)
typedef uint8_t PPSMC_Result;
#define PPSMC_MSG_Halt ((uint8_t)0x10)
#define PPSMC_MSG_Resume ((uint8_t)0x11)
#define PPSMC_MSG_ZeroLevelsDisabled ((uint8_t)0x13)
#define PPSMC_MSG_OneLevelsDisabled ((uint8_t)0x14)
#define PPSMC_MSG_TwoLevelsDisabled ((uint8_t)0x15)
#define PPSMC_MSG_EnableThermalInterrupt ((uint8_t)0x16)
#define PPSMC_MSG_RunningOnAC ((uint8_t)0x17)
#define PPSMC_MSG_SwitchToSwState ((uint8_t)0x20)
#define PPSMC_MSG_SwitchToInitialState ((uint8_t)0x40)
#define PPSMC_MSG_NoForcedLevel ((uint8_t)0x41)
#define PPSMC_MSG_ForceHigh ((uint8_t)0x42)
#define PPSMC_MSG_ForceMediumOrHigh ((uint8_t)0x43)
#define PPSMC_MSG_SwitchToMinimumPower ((uint8_t)0x51)
#define PPSMC_MSG_ResumeFromMinimumPower ((uint8_t)0x52)
#define PPSMC_MSG_EnableCac ((uint8_t)0x53)
#define PPSMC_MSG_DisableCac ((uint8_t)0x54)
#define PPSMC_TDPClampingActive ((uint8_t)0x59)
#define PPSMC_TDPClampingInactive ((uint8_t)0x5A)
#define PPSMC_StartFanControl ((uint8_t)0x5B)
#define PPSMC_StopFanControl ((uint8_t)0x5C)
#define PPSMC_MSG_NoDisplay ((uint8_t)0x5D)
#define PPSMC_NoDisplay ((uint8_t)0x5D)
#define PPSMC_MSG_HasDisplay ((uint8_t)0x5E)
#define PPSMC_HasDisplay ((uint8_t)0x5E)
#define PPSMC_MSG_UVDPowerOFF ((uint8_t)0x60)
#define PPSMC_MSG_UVDPowerON ((uint8_t)0x61)
#define PPSMC_MSG_EnableULV ((uint8_t)0x62)
#define PPSMC_MSG_DisableULV ((uint8_t)0x63)
#define PPSMC_MSG_EnterULV ((uint8_t)0x64)
#define PPSMC_MSG_ExitULV ((uint8_t)0x65)
#define PPSMC_CACLongTermAvgEnable ((uint8_t)0x6E)
#define PPSMC_CACLongTermAvgDisable ((uint8_t)0x6F)
#define PPSMC_MSG_CollectCAC_PowerCorreln ((uint8_t)0x7A)
#define PPSMC_FlushDataCache ((uint8_t)0x80)
#define PPSMC_MSG_SetEnabledLevels ((uint8_t)0x82)
#define PPSMC_MSG_SetForcedLevels ((uint8_t)0x83)
#define PPSMC_MSG_ResetToDefaults ((uint8_t)0x84)
#define PPSMC_MSG_EnableDTE ((uint8_t)0x87)
#define PPSMC_MSG_DisableDTE ((uint8_t)0x88)
#define PPSMC_MSG_ThrottleOVRDSCLKDS ((uint8_t)0x96)
#define PPSMC_MSG_CancelThrottleOVRDSCLKDS ((uint8_t)0x97)
#define PPSMC_MSG_EnableACDCGPIOInterrupt ((uint16_t) 0x149)
/* CI/KV/KB */
#define PPSMC_MSG_UVDDPM_SetEnabledMask ((uint16_t) 0x12D)
#define PPSMC_MSG_VCEDPM_SetEnabledMask ((uint16_t) 0x12E)
#define PPSMC_MSG_ACPDPM_SetEnabledMask ((uint16_t) 0x12F)
#define PPSMC_MSG_SAMUDPM_SetEnabledMask ((uint16_t) 0x130)
#define PPSMC_MSG_MCLKDPM_ForceState ((uint16_t) 0x131)
#define PPSMC_MSG_MCLKDPM_NoForcedLevel ((uint16_t) 0x132)
#define PPSMC_MSG_Thermal_Cntl_Disable ((uint16_t) 0x133)
#define PPSMC_MSG_Voltage_Cntl_Disable ((uint16_t) 0x135)
#define PPSMC_MSG_PCIeDPM_Enable ((uint16_t) 0x136)
#define PPSMC_MSG_PCIeDPM_Disable ((uint16_t) 0x13d)
#define PPSMC_MSG_ACPPowerOFF ((uint16_t) 0x137)
#define PPSMC_MSG_ACPPowerON ((uint16_t) 0x138)
#define PPSMC_MSG_SAMPowerOFF ((uint16_t) 0x139)
#define PPSMC_MSG_SAMPowerON ((uint16_t) 0x13a)
#define PPSMC_MSG_PCIeDPM_Disable ((uint16_t) 0x13d)
#define PPSMC_MSG_NBDPM_Enable ((uint16_t) 0x140)
#define PPSMC_MSG_NBDPM_Disable ((uint16_t) 0x141)
#define PPSMC_MSG_SCLKDPM_SetEnabledMask ((uint16_t) 0x145)
#define PPSMC_MSG_MCLKDPM_SetEnabledMask ((uint16_t) 0x146)
#define PPSMC_MSG_PCIeDPM_ForceLevel ((uint16_t) 0x147)
#define PPSMC_MSG_PCIeDPM_UnForceLevel ((uint16_t) 0x148)
#define PPSMC_MSG_EnableVRHotGPIOInterrupt ((uint16_t) 0x14a)
#define PPSMC_MSG_DPM_Enable ((uint16_t) 0x14e)
#define PPSMC_MSG_DPM_Disable ((uint16_t) 0x14f)
#define PPSMC_MSG_MCLKDPM_Enable ((uint16_t) 0x150)
#define PPSMC_MSG_MCLKDPM_Disable ((uint16_t) 0x151)
#define PPSMC_MSG_UVDDPM_Enable ((uint16_t) 0x154)
#define PPSMC_MSG_UVDDPM_Disable ((uint16_t) 0x155)
#define PPSMC_MSG_SAMUDPM_Enable ((uint16_t) 0x156)
#define PPSMC_MSG_SAMUDPM_Disable ((uint16_t) 0x157)
#define PPSMC_MSG_ACPDPM_Enable ((uint16_t) 0x158)
#define PPSMC_MSG_ACPDPM_Disable ((uint16_t) 0x159)
#define PPSMC_MSG_VCEDPM_Enable ((uint16_t) 0x15a)
#define PPSMC_MSG_VCEDPM_Disable ((uint16_t) 0x15b)
#define PPSMC_MSG_VddC_Request ((uint16_t) 0x15f)
#define PPSMC_MSG_SCLKDPM_GetEnabledMask ((uint16_t) 0x162)
#define PPSMC_MSG_PCIeDPM_SetEnabledMask ((uint16_t) 0x167)
#define PPSMC_MSG_TDCLimitEnable ((uint16_t) 0x169)
#define PPSMC_MSG_TDCLimitDisable ((uint16_t) 0x16a)
#define PPSMC_MSG_PkgPwrLimitEnable ((uint16_t) 0x185)
#define PPSMC_MSG_PkgPwrLimitDisable ((uint16_t) 0x186)
#define PPSMC_MSG_PkgPwrSetLimit ((uint16_t) 0x187)
#define PPSMC_MSG_OverDriveSetTargetTdp ((uint16_t) 0x188)
#define PPSMC_MSG_SCLKDPM_FreezeLevel ((uint16_t) 0x189)
#define PPSMC_MSG_SCLKDPM_UnfreezeLevel ((uint16_t) 0x18A)
#define PPSMC_MSG_MCLKDPM_FreezeLevel ((uint16_t) 0x18B)
#define PPSMC_MSG_MCLKDPM_UnfreezeLevel ((uint16_t) 0x18C)
#define PPSMC_MSG_MASTER_DeepSleep_ON ((uint16_t) 0x18F)
#define PPSMC_MSG_MASTER_DeepSleep_OFF ((uint16_t) 0x190)
#define PPSMC_MSG_Remove_DC_Clamp ((uint16_t) 0x191)
#define PPSMC_MSG_SetFanPwmMax ((uint16_t) 0x19A)
#define PPSMC_MSG_SetFanRpmMax ((uint16_t) 0x205)
#define PPSMC_MSG_ENABLE_THERMAL_DPM ((uint16_t) 0x19C)
#define PPSMC_MSG_DISABLE_THERMAL_DPM ((uint16_t) 0x19D)
#define PPSMC_MSG_API_GetSclkFrequency ((uint16_t) 0x200)
#define PPSMC_MSG_API_GetMclkFrequency ((uint16_t) 0x201)
/* TN */
#define PPSMC_MSG_DPM_Config ((uint32_t) 0x102)
#define PPSMC_MSG_DPM_ForceState ((uint32_t) 0x104)
#define PPSMC_MSG_PG_SIMD_Config ((uint32_t) 0x108)
#define PPSMC_MSG_Voltage_Cntl_Enable ((uint32_t) 0x109)
#define PPSMC_MSG_Thermal_Cntl_Enable ((uint32_t) 0x10a)
#define PPSMC_MSG_VCEPowerOFF ((uint32_t) 0x10e)
#define PPSMC_MSG_VCEPowerON ((uint32_t) 0x10f)
#define PPSMC_MSG_DPM_N_LevelsDisabled ((uint32_t) 0x112)
#define PPSMC_MSG_DCE_RemoveVoltageAdjustment ((uint32_t) 0x11d)
#define PPSMC_MSG_DCE_AllowVoltageAdjustment ((uint32_t) 0x11e)
#define PPSMC_MSG_EnableBAPM ((uint32_t) 0x120)
#define PPSMC_MSG_DisableBAPM ((uint32_t) 0x121)
#define PPSMC_MSG_UVD_DPM_Config ((uint32_t) 0x124)
#define PPSMC_MSG_DRV_DRAM_ADDR_HI ((uint16_t) 0x250)
#define PPSMC_MSG_DRV_DRAM_ADDR_LO ((uint16_t) 0x251)
#define PPSMC_MSG_SMU_DRAM_ADDR_HI ((uint16_t) 0x252)
#define PPSMC_MSG_SMU_DRAM_ADDR_LO ((uint16_t) 0x253)
#define PPSMC_MSG_LoadUcodes ((uint16_t) 0x254)
typedef uint16_t PPSMC_Msg;
#pragma pack(pop)
#endif

View File

@@ -0,0 +1,127 @@
/*
* Copyright 2011 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.
*
*/
#ifndef __R600_DPM_H__
#define __R600_DPM_H__
#define R600_ASI_DFLT 10000
#define R600_BSP_DFLT 0x41EB
#define R600_BSU_DFLT 0x2
#define R600_AH_DFLT 5
#define R600_RLP_DFLT 25
#define R600_RMP_DFLT 65
#define R600_LHP_DFLT 40
#define R600_LMP_DFLT 15
#define R600_TD_DFLT 0
#define R600_UTC_DFLT_00 0x24
#define R600_UTC_DFLT_01 0x22
#define R600_UTC_DFLT_02 0x22
#define R600_UTC_DFLT_03 0x22
#define R600_UTC_DFLT_04 0x22
#define R600_UTC_DFLT_05 0x22
#define R600_UTC_DFLT_06 0x22
#define R600_UTC_DFLT_07 0x22
#define R600_UTC_DFLT_08 0x22
#define R600_UTC_DFLT_09 0x22
#define R600_UTC_DFLT_10 0x22
#define R600_UTC_DFLT_11 0x22
#define R600_UTC_DFLT_12 0x22
#define R600_UTC_DFLT_13 0x22
#define R600_UTC_DFLT_14 0x22
#define R600_DTC_DFLT_00 0x24
#define R600_DTC_DFLT_01 0x22
#define R600_DTC_DFLT_02 0x22
#define R600_DTC_DFLT_03 0x22
#define R600_DTC_DFLT_04 0x22
#define R600_DTC_DFLT_05 0x22
#define R600_DTC_DFLT_06 0x22
#define R600_DTC_DFLT_07 0x22
#define R600_DTC_DFLT_08 0x22
#define R600_DTC_DFLT_09 0x22
#define R600_DTC_DFLT_10 0x22
#define R600_DTC_DFLT_11 0x22
#define R600_DTC_DFLT_12 0x22
#define R600_DTC_DFLT_13 0x22
#define R600_DTC_DFLT_14 0x22
#define R600_VRC_DFLT 0x0000C003
#define R600_VOLTAGERESPONSETIME_DFLT 1000
#define R600_BACKBIASRESPONSETIME_DFLT 1000
#define R600_VRU_DFLT 0x3
#define R600_SPLLSTEPTIME_DFLT 0x1000
#define R600_SPLLSTEPUNIT_DFLT 0x3
#define R600_TPU_DFLT 0
#define R600_TPC_DFLT 0x200
#define R600_SSTU_DFLT 0
#define R600_SST_DFLT 0x00C8
#define R600_GICST_DFLT 0x200
#define R600_FCT_DFLT 0x0400
#define R600_FCTU_DFLT 0
#define R600_CTXCGTT3DRPHC_DFLT 0x20
#define R600_CTXCGTT3DRSDC_DFLT 0x40
#define R600_VDDC3DOORPHC_DFLT 0x100
#define R600_VDDC3DOORSDC_DFLT 0x7
#define R600_VDDC3DOORSU_DFLT 0
#define R600_MPLLLOCKTIME_DFLT 100
#define R600_MPLLRESETTIME_DFLT 150
#define R600_VCOSTEPPCT_DFLT 20
#define R600_ENDINGVCOSTEPPCT_DFLT 5
#define R600_REFERENCEDIVIDER_DFLT 4
#define R600_PM_NUMBER_OF_TC 15
#define R600_PM_NUMBER_OF_SCLKS 20
#define R600_PM_NUMBER_OF_MCLKS 4
#define R600_PM_NUMBER_OF_VOLTAGE_LEVELS 4
#define R600_PM_NUMBER_OF_ACTIVITY_LEVELS 3
/* XXX are these ok? */
#define R600_TEMP_RANGE_MIN (90 * 1000)
#define R600_TEMP_RANGE_MAX (120 * 1000)
#define FDO_PWM_MODE_STATIC 1
#define FDO_PWM_MODE_STATIC_RPM 5
enum r600_power_level {
R600_POWER_LEVEL_LOW = 0,
R600_POWER_LEVEL_MEDIUM = 1,
R600_POWER_LEVEL_HIGH = 2,
R600_POWER_LEVEL_CTXSW = 3,
};
enum r600_td {
R600_TD_AUTO,
R600_TD_UP,
R600_TD_DOWN,
};
enum r600_display_watermark {
R600_DISPLAY_WATERMARK_LOW = 0,
R600_DISPLAY_WATERMARK_HIGH = 1,
};
enum r600_display_gap
{
R600_PM_DISPLAY_GAP_VBLANK_OR_WM = 0,
R600_PM_DISPLAY_GAP_VBLANK = 1,
R600_PM_DISPLAY_GAP_WATERMARK = 2,
R600_PM_DISPLAY_GAP_IGNORE = 3,
};
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,273 @@
/*
* Copyright 2011 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.
*
* Authors: Alex Deucher
*/
#include <linux/firmware.h>
#include "amdgpu.h"
#include "sid.h"
#include "ppsmc.h"
#include "amdgpu_ucode.h"
#include "sislands_smc.h"
static int si_set_smc_sram_address(struct amdgpu_device *adev,
u32 smc_address, u32 limit)
{
if (smc_address & 3)
return -EINVAL;
if ((smc_address + 3) > limit)
return -EINVAL;
WREG32(SMC_IND_INDEX_0, smc_address);
WREG32_P(SMC_IND_ACCESS_CNTL, 0, ~AUTO_INCREMENT_IND_0);
return 0;
}
int amdgpu_si_copy_bytes_to_smc(struct amdgpu_device *adev,
u32 smc_start_address,
const u8 *src, u32 byte_count, u32 limit)
{
unsigned long flags;
int ret = 0;
u32 data, original_data, addr, extra_shift;
if (smc_start_address & 3)
return -EINVAL;
if ((smc_start_address + byte_count) > limit)
return -EINVAL;
addr = smc_start_address;
spin_lock_irqsave(&adev->smc_idx_lock, flags);
while (byte_count >= 4) {
/* SMC address space is BE */
data = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
ret = si_set_smc_sram_address(adev, addr, limit);
if (ret)
goto done;
WREG32(SMC_IND_DATA_0, data);
src += 4;
byte_count -= 4;
addr += 4;
}
/* RMW for the final bytes */
if (byte_count > 0) {
data = 0;
ret = si_set_smc_sram_address(adev, addr, limit);
if (ret)
goto done;
original_data = RREG32(SMC_IND_DATA_0);
extra_shift = 8 * (4 - byte_count);
while (byte_count > 0) {
/* SMC address space is BE */
data = (data << 8) + *src++;
byte_count--;
}
data <<= extra_shift;
data |= (original_data & ~((~0UL) << extra_shift));
ret = si_set_smc_sram_address(adev, addr, limit);
if (ret)
goto done;
WREG32(SMC_IND_DATA_0, data);
}
done:
spin_unlock_irqrestore(&adev->smc_idx_lock, flags);
return ret;
}
void amdgpu_si_start_smc(struct amdgpu_device *adev)
{
u32 tmp = RREG32_SMC(SMC_SYSCON_RESET_CNTL);
tmp &= ~RST_REG;
WREG32_SMC(SMC_SYSCON_RESET_CNTL, tmp);
}
void amdgpu_si_reset_smc(struct amdgpu_device *adev)
{
u32 tmp;
RREG32(CB_CGTT_SCLK_CTRL);
RREG32(CB_CGTT_SCLK_CTRL);
RREG32(CB_CGTT_SCLK_CTRL);
RREG32(CB_CGTT_SCLK_CTRL);
tmp = RREG32_SMC(SMC_SYSCON_RESET_CNTL) |
RST_REG;
WREG32_SMC(SMC_SYSCON_RESET_CNTL, tmp);
}
int amdgpu_si_program_jump_on_start(struct amdgpu_device *adev)
{
static const u8 data[] = { 0x0E, 0x00, 0x40, 0x40 };
return amdgpu_si_copy_bytes_to_smc(adev, 0x0, data, 4, sizeof(data)+1);
}
void amdgpu_si_smc_clock(struct amdgpu_device *adev, bool enable)
{
u32 tmp = RREG32_SMC(SMC_SYSCON_CLOCK_CNTL_0);
if (enable)
tmp &= ~CK_DISABLE;
else
tmp |= CK_DISABLE;
WREG32_SMC(SMC_SYSCON_CLOCK_CNTL_0, tmp);
}
bool amdgpu_si_is_smc_running(struct amdgpu_device *adev)
{
u32 rst = RREG32_SMC(SMC_SYSCON_RESET_CNTL);
u32 clk = RREG32_SMC(SMC_SYSCON_CLOCK_CNTL_0);
if (!(rst & RST_REG) && !(clk & CK_DISABLE))
return true;
return false;
}
PPSMC_Result amdgpu_si_send_msg_to_smc(struct amdgpu_device *adev,
PPSMC_Msg msg)
{
u32 tmp;
int i;
if (!amdgpu_si_is_smc_running(adev))
return PPSMC_Result_Failed;
WREG32(SMC_MESSAGE_0, msg);
for (i = 0; i < adev->usec_timeout; i++) {
tmp = RREG32(SMC_RESP_0);
if (tmp != 0)
break;
udelay(1);
}
return (PPSMC_Result)RREG32(SMC_RESP_0);
}
PPSMC_Result amdgpu_si_wait_for_smc_inactive(struct amdgpu_device *adev)
{
u32 tmp;
int i;
if (!amdgpu_si_is_smc_running(adev))
return PPSMC_Result_OK;
for (i = 0; i < adev->usec_timeout; i++) {
tmp = RREG32_SMC(SMC_SYSCON_CLOCK_CNTL_0);
if ((tmp & CKEN) == 0)
break;
udelay(1);
}
return PPSMC_Result_OK;
}
int amdgpu_si_load_smc_ucode(struct amdgpu_device *adev, u32 limit)
{
const struct smc_firmware_header_v1_0 *hdr;
unsigned long flags;
u32 ucode_start_address;
u32 ucode_size;
const u8 *src;
u32 data;
if (!adev->pm.fw)
return -EINVAL;
hdr = (const struct smc_firmware_header_v1_0 *)adev->pm.fw->data;
amdgpu_ucode_print_smc_hdr(&hdr->header);
adev->pm.fw_version = le32_to_cpu(hdr->header.ucode_version);
ucode_start_address = le32_to_cpu(hdr->ucode_start_addr);
ucode_size = le32_to_cpu(hdr->header.ucode_size_bytes);
src = (const u8 *)
(adev->pm.fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
if (ucode_size & 3)
return -EINVAL;
spin_lock_irqsave(&adev->smc_idx_lock, flags);
WREG32(SMC_IND_INDEX_0, ucode_start_address);
WREG32_P(SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, ~AUTO_INCREMENT_IND_0);
while (ucode_size >= 4) {
/* SMC address space is BE */
data = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
WREG32(SMC_IND_DATA_0, data);
src += 4;
ucode_size -= 4;
}
WREG32_P(SMC_IND_ACCESS_CNTL, 0, ~AUTO_INCREMENT_IND_0);
spin_unlock_irqrestore(&adev->smc_idx_lock, flags);
return 0;
}
int amdgpu_si_read_smc_sram_dword(struct amdgpu_device *adev, u32 smc_address,
u32 *value, u32 limit)
{
unsigned long flags;
int ret;
spin_lock_irqsave(&adev->smc_idx_lock, flags);
ret = si_set_smc_sram_address(adev, smc_address, limit);
if (ret == 0)
*value = RREG32(SMC_IND_DATA_0);
spin_unlock_irqrestore(&adev->smc_idx_lock, flags);
return ret;
}
int amdgpu_si_write_smc_sram_dword(struct amdgpu_device *adev, u32 smc_address,
u32 value, u32 limit)
{
unsigned long flags;
int ret;
spin_lock_irqsave(&adev->smc_idx_lock, flags);
ret = si_set_smc_sram_address(adev, smc_address, limit);
if (ret == 0)
WREG32(SMC_IND_DATA_0, value);
spin_unlock_irqrestore(&adev->smc_idx_lock, flags);
return ret;
}

View File

@@ -0,0 +1,423 @@
/*
* Copyright 2013 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.
*
*/
#ifndef PP_SISLANDS_SMC_H
#define PP_SISLANDS_SMC_H
#include "ppsmc.h"
#pragma pack(push, 1)
#define SISLANDS_MAX_SMC_PERFORMANCE_LEVELS_PER_SWSTATE 16
struct PP_SIslands_Dpm2PerfLevel
{
uint8_t MaxPS;
uint8_t TgtAct;
uint8_t MaxPS_StepInc;
uint8_t MaxPS_StepDec;
uint8_t PSSamplingTime;
uint8_t NearTDPDec;
uint8_t AboveSafeInc;
uint8_t BelowSafeInc;
uint8_t PSDeltaLimit;
uint8_t PSDeltaWin;
uint16_t PwrEfficiencyRatio;
uint8_t Reserved[4];
};
typedef struct PP_SIslands_Dpm2PerfLevel PP_SIslands_Dpm2PerfLevel;
struct PP_SIslands_DPM2Status
{
uint32_t dpm2Flags;
uint8_t CurrPSkip;
uint8_t CurrPSkipPowerShift;
uint8_t CurrPSkipTDP;
uint8_t CurrPSkipOCP;
uint8_t MaxSPLLIndex;
uint8_t MinSPLLIndex;
uint8_t CurrSPLLIndex;
uint8_t InfSweepMode;
uint8_t InfSweepDir;
uint8_t TDPexceeded;
uint8_t reserved;
uint8_t SwitchDownThreshold;
uint32_t SwitchDownCounter;
uint32_t SysScalingFactor;
};
typedef struct PP_SIslands_DPM2Status PP_SIslands_DPM2Status;
struct PP_SIslands_DPM2Parameters
{
uint32_t TDPLimit;
uint32_t NearTDPLimit;
uint32_t SafePowerLimit;
uint32_t PowerBoostLimit;
uint32_t MinLimitDelta;
};
typedef struct PP_SIslands_DPM2Parameters PP_SIslands_DPM2Parameters;
struct PP_SIslands_PAPMStatus
{
uint32_t EstimatedDGPU_T;
uint32_t EstimatedDGPU_P;
uint32_t EstimatedAPU_T;
uint32_t EstimatedAPU_P;
uint8_t dGPU_T_Limit_Exceeded;
uint8_t reserved[3];
};
typedef struct PP_SIslands_PAPMStatus PP_SIslands_PAPMStatus;
struct PP_SIslands_PAPMParameters
{
uint32_t NearTDPLimitTherm;
uint32_t NearTDPLimitPAPM;
uint32_t PlatformPowerLimit;
uint32_t dGPU_T_Limit;
uint32_t dGPU_T_Warning;
uint32_t dGPU_T_Hysteresis;
};
typedef struct PP_SIslands_PAPMParameters PP_SIslands_PAPMParameters;
struct SISLANDS_SMC_SCLK_VALUE
{
uint32_t vCG_SPLL_FUNC_CNTL;
uint32_t vCG_SPLL_FUNC_CNTL_2;
uint32_t vCG_SPLL_FUNC_CNTL_3;
uint32_t vCG_SPLL_FUNC_CNTL_4;
uint32_t vCG_SPLL_SPREAD_SPECTRUM;
uint32_t vCG_SPLL_SPREAD_SPECTRUM_2;
uint32_t sclk_value;
};
typedef struct SISLANDS_SMC_SCLK_VALUE SISLANDS_SMC_SCLK_VALUE;
struct SISLANDS_SMC_MCLK_VALUE
{
uint32_t vMPLL_FUNC_CNTL;
uint32_t vMPLL_FUNC_CNTL_1;
uint32_t vMPLL_FUNC_CNTL_2;
uint32_t vMPLL_AD_FUNC_CNTL;
uint32_t vMPLL_DQ_FUNC_CNTL;
uint32_t vMCLK_PWRMGT_CNTL;
uint32_t vDLL_CNTL;
uint32_t vMPLL_SS;
uint32_t vMPLL_SS2;
uint32_t mclk_value;
};
typedef struct SISLANDS_SMC_MCLK_VALUE SISLANDS_SMC_MCLK_VALUE;
struct SISLANDS_SMC_VOLTAGE_VALUE
{
uint16_t value;
uint8_t index;
uint8_t phase_settings;
};
typedef struct SISLANDS_SMC_VOLTAGE_VALUE SISLANDS_SMC_VOLTAGE_VALUE;
struct SISLANDS_SMC_HW_PERFORMANCE_LEVEL
{
uint8_t ACIndex;
uint8_t displayWatermark;
uint8_t gen2PCIE;
uint8_t UVDWatermark;
uint8_t VCEWatermark;
uint8_t strobeMode;
uint8_t mcFlags;
uint8_t padding;
uint32_t aT;
uint32_t bSP;
SISLANDS_SMC_SCLK_VALUE sclk;
SISLANDS_SMC_MCLK_VALUE mclk;
SISLANDS_SMC_VOLTAGE_VALUE vddc;
SISLANDS_SMC_VOLTAGE_VALUE mvdd;
SISLANDS_SMC_VOLTAGE_VALUE vddci;
SISLANDS_SMC_VOLTAGE_VALUE std_vddc;
uint8_t hysteresisUp;
uint8_t hysteresisDown;
uint8_t stateFlags;
uint8_t arbRefreshState;
uint32_t SQPowerThrottle;
uint32_t SQPowerThrottle_2;
uint32_t MaxPoweredUpCU;
SISLANDS_SMC_VOLTAGE_VALUE high_temp_vddc;
SISLANDS_SMC_VOLTAGE_VALUE low_temp_vddc;
uint32_t reserved[2];
PP_SIslands_Dpm2PerfLevel dpm2;
};
#define SISLANDS_SMC_STROBE_RATIO 0x0F
#define SISLANDS_SMC_STROBE_ENABLE 0x10
#define SISLANDS_SMC_MC_EDC_RD_FLAG 0x01
#define SISLANDS_SMC_MC_EDC_WR_FLAG 0x02
#define SISLANDS_SMC_MC_RTT_ENABLE 0x04
#define SISLANDS_SMC_MC_STUTTER_EN 0x08
#define SISLANDS_SMC_MC_PG_EN 0x10
typedef struct SISLANDS_SMC_HW_PERFORMANCE_LEVEL SISLANDS_SMC_HW_PERFORMANCE_LEVEL;
struct SISLANDS_SMC_SWSTATE
{
uint8_t flags;
uint8_t levelCount;
uint8_t padding2;
uint8_t padding3;
SISLANDS_SMC_HW_PERFORMANCE_LEVEL levels[1];
};
typedef struct SISLANDS_SMC_SWSTATE SISLANDS_SMC_SWSTATE;
#define SISLANDS_SMC_VOLTAGEMASK_VDDC 0
#define SISLANDS_SMC_VOLTAGEMASK_MVDD 1
#define SISLANDS_SMC_VOLTAGEMASK_VDDCI 2
#define SISLANDS_SMC_VOLTAGEMASK_VDDC_PHASE_SHEDDING 3
#define SISLANDS_SMC_VOLTAGEMASK_MAX 4
struct SISLANDS_SMC_VOLTAGEMASKTABLE
{
uint32_t lowMask[SISLANDS_SMC_VOLTAGEMASK_MAX];
};
typedef struct SISLANDS_SMC_VOLTAGEMASKTABLE SISLANDS_SMC_VOLTAGEMASKTABLE;
#define SISLANDS_MAX_NO_VREG_STEPS 32
struct SISLANDS_SMC_STATETABLE
{
uint8_t thermalProtectType;
uint8_t systemFlags;
uint8_t maxVDDCIndexInPPTable;
uint8_t extraFlags;
uint32_t lowSMIO[SISLANDS_MAX_NO_VREG_STEPS];
SISLANDS_SMC_VOLTAGEMASKTABLE voltageMaskTable;
SISLANDS_SMC_VOLTAGEMASKTABLE phaseMaskTable;
PP_SIslands_DPM2Parameters dpm2Params;
SISLANDS_SMC_SWSTATE initialState;
SISLANDS_SMC_SWSTATE ACPIState;
SISLANDS_SMC_SWSTATE ULVState;
SISLANDS_SMC_SWSTATE driverState;
SISLANDS_SMC_HW_PERFORMANCE_LEVEL dpmLevels[SISLANDS_MAX_SMC_PERFORMANCE_LEVELS_PER_SWSTATE - 1];
};
typedef struct SISLANDS_SMC_STATETABLE SISLANDS_SMC_STATETABLE;
#define SI_SMC_SOFT_REGISTER_mclk_chg_timeout 0x0
#define SI_SMC_SOFT_REGISTER_delay_vreg 0xC
#define SI_SMC_SOFT_REGISTER_delay_acpi 0x28
#define SI_SMC_SOFT_REGISTER_seq_index 0x5C
#define SI_SMC_SOFT_REGISTER_mvdd_chg_time 0x60
#define SI_SMC_SOFT_REGISTER_mclk_switch_lim 0x70
#define SI_SMC_SOFT_REGISTER_watermark_threshold 0x78
#define SI_SMC_SOFT_REGISTER_phase_shedding_delay 0x88
#define SI_SMC_SOFT_REGISTER_ulv_volt_change_delay 0x8C
#define SI_SMC_SOFT_REGISTER_mc_block_delay 0x98
#define SI_SMC_SOFT_REGISTER_ticks_per_us 0xA8
#define SI_SMC_SOFT_REGISTER_crtc_index 0xC4
#define SI_SMC_SOFT_REGISTER_mclk_change_block_cp_min 0xC8
#define SI_SMC_SOFT_REGISTER_mclk_change_block_cp_max 0xCC
#define SI_SMC_SOFT_REGISTER_non_ulv_pcie_link_width 0xF4
#define SI_SMC_SOFT_REGISTER_tdr_is_about_to_happen 0xFC
#define SI_SMC_SOFT_REGISTER_vr_hot_gpio 0x100
#define SI_SMC_SOFT_REGISTER_svi_rework_plat_type 0x118
#define SI_SMC_SOFT_REGISTER_svi_rework_gpio_id_svd 0x11c
#define SI_SMC_SOFT_REGISTER_svi_rework_gpio_id_svc 0x120
struct PP_SIslands_FanTable
{
uint8_t fdo_mode;
uint8_t padding;
int16_t temp_min;
int16_t temp_med;
int16_t temp_max;
int16_t slope1;
int16_t slope2;
int16_t fdo_min;
int16_t hys_up;
int16_t hys_down;
int16_t hys_slope;
int16_t temp_resp_lim;
int16_t temp_curr;
int16_t slope_curr;
int16_t pwm_curr;
uint32_t refresh_period;
int16_t fdo_max;
uint8_t temp_src;
int8_t padding2;
};
typedef struct PP_SIslands_FanTable PP_SIslands_FanTable;
#define SMC_SISLANDS_LKGE_LUT_NUM_OF_TEMP_ENTRIES 16
#define SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES 32
#define SMC_SISLANDS_SCALE_I 7
#define SMC_SISLANDS_SCALE_R 12
struct PP_SIslands_CacConfig
{
uint16_t cac_lkge_lut[SMC_SISLANDS_LKGE_LUT_NUM_OF_TEMP_ENTRIES][SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES];
uint32_t lkge_lut_V0;
uint32_t lkge_lut_Vstep;
uint32_t WinTime;
uint32_t R_LL;
uint32_t calculation_repeats;
uint32_t l2numWin_TDP;
uint32_t dc_cac;
uint8_t lts_truncate_n;
uint8_t SHIFT_N;
uint8_t log2_PG_LKG_SCALE;
uint8_t cac_temp;
uint32_t lkge_lut_T0;
uint32_t lkge_lut_Tstep;
};
typedef struct PP_SIslands_CacConfig PP_SIslands_CacConfig;
#define SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE 16
#define SMC_SISLANDS_MC_REGISTER_ARRAY_SET_COUNT 20
struct SMC_SIslands_MCRegisterAddress
{
uint16_t s0;
uint16_t s1;
};
typedef struct SMC_SIslands_MCRegisterAddress SMC_SIslands_MCRegisterAddress;
struct SMC_SIslands_MCRegisterSet
{
uint32_t value[SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE];
};
typedef struct SMC_SIslands_MCRegisterSet SMC_SIslands_MCRegisterSet;
struct SMC_SIslands_MCRegisters
{
uint8_t last;
uint8_t reserved[3];
SMC_SIslands_MCRegisterAddress address[SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE];
SMC_SIslands_MCRegisterSet data[SMC_SISLANDS_MC_REGISTER_ARRAY_SET_COUNT];
};
typedef struct SMC_SIslands_MCRegisters SMC_SIslands_MCRegisters;
struct SMC_SIslands_MCArbDramTimingRegisterSet
{
uint32_t mc_arb_dram_timing;
uint32_t mc_arb_dram_timing2;
uint8_t mc_arb_rfsh_rate;
uint8_t mc_arb_burst_time;
uint8_t padding[2];
};
typedef struct SMC_SIslands_MCArbDramTimingRegisterSet SMC_SIslands_MCArbDramTimingRegisterSet;
struct SMC_SIslands_MCArbDramTimingRegisters
{
uint8_t arb_current;
uint8_t reserved[3];
SMC_SIslands_MCArbDramTimingRegisterSet data[16];
};
typedef struct SMC_SIslands_MCArbDramTimingRegisters SMC_SIslands_MCArbDramTimingRegisters;
struct SMC_SISLANDS_SPLL_DIV_TABLE
{
uint32_t freq[256];
uint32_t ss[256];
};
#define SMC_SISLANDS_SPLL_DIV_TABLE_FBDIV_MASK 0x01ffffff
#define SMC_SISLANDS_SPLL_DIV_TABLE_FBDIV_SHIFT 0
#define SMC_SISLANDS_SPLL_DIV_TABLE_PDIV_MASK 0xfe000000
#define SMC_SISLANDS_SPLL_DIV_TABLE_PDIV_SHIFT 25
#define SMC_SISLANDS_SPLL_DIV_TABLE_CLKV_MASK 0x000fffff
#define SMC_SISLANDS_SPLL_DIV_TABLE_CLKV_SHIFT 0
#define SMC_SISLANDS_SPLL_DIV_TABLE_CLKS_MASK 0xfff00000
#define SMC_SISLANDS_SPLL_DIV_TABLE_CLKS_SHIFT 20
typedef struct SMC_SISLANDS_SPLL_DIV_TABLE SMC_SISLANDS_SPLL_DIV_TABLE;
#define SMC_SISLANDS_DTE_MAX_FILTER_STAGES 5
#define SMC_SISLANDS_DTE_MAX_TEMPERATURE_DEPENDENT_ARRAY_SIZE 16
struct Smc_SIslands_DTE_Configuration
{
uint32_t tau[SMC_SISLANDS_DTE_MAX_FILTER_STAGES];
uint32_t R[SMC_SISLANDS_DTE_MAX_FILTER_STAGES];
uint32_t K;
uint32_t T0;
uint32_t MaxT;
uint8_t WindowSize;
uint8_t Tdep_count;
uint8_t temp_select;
uint8_t DTE_mode;
uint8_t T_limits[SMC_SISLANDS_DTE_MAX_TEMPERATURE_DEPENDENT_ARRAY_SIZE];
uint32_t Tdep_tau[SMC_SISLANDS_DTE_MAX_TEMPERATURE_DEPENDENT_ARRAY_SIZE];
uint32_t Tdep_R[SMC_SISLANDS_DTE_MAX_TEMPERATURE_DEPENDENT_ARRAY_SIZE];
uint32_t Tthreshold;
};
typedef struct Smc_SIslands_DTE_Configuration Smc_SIslands_DTE_Configuration;
#define SMC_SISLANDS_DTE_STATUS_FLAG_DTE_ON 1
#define SISLANDS_SMC_FIRMWARE_HEADER_LOCATION 0x10000
#define SISLANDS_SMC_FIRMWARE_HEADER_version 0x0
#define SISLANDS_SMC_FIRMWARE_HEADER_flags 0x4
#define SISLANDS_SMC_FIRMWARE_HEADER_softRegisters 0xC
#define SISLANDS_SMC_FIRMWARE_HEADER_stateTable 0x10
#define SISLANDS_SMC_FIRMWARE_HEADER_fanTable 0x14
#define SISLANDS_SMC_FIRMWARE_HEADER_CacConfigTable 0x18
#define SISLANDS_SMC_FIRMWARE_HEADER_mcRegisterTable 0x24
#define SISLANDS_SMC_FIRMWARE_HEADER_mcArbDramAutoRefreshTable 0x30
#define SISLANDS_SMC_FIRMWARE_HEADER_spllTable 0x38
#define SISLANDS_SMC_FIRMWARE_HEADER_DteConfiguration 0x40
#define SISLANDS_SMC_FIRMWARE_HEADER_PAPMParameters 0x48
#pragma pack(pop)
int amdgpu_si_copy_bytes_to_smc(struct amdgpu_device *adev,
u32 smc_start_address,
const u8 *src, u32 byte_count, u32 limit);
void amdgpu_si_start_smc(struct amdgpu_device *adev);
void amdgpu_si_reset_smc(struct amdgpu_device *adev);
int amdgpu_si_program_jump_on_start(struct amdgpu_device *adev);
void amdgpu_si_smc_clock(struct amdgpu_device *adev, bool enable);
bool amdgpu_si_is_smc_running(struct amdgpu_device *adev);
PPSMC_Result amdgpu_si_send_msg_to_smc(struct amdgpu_device *adev, PPSMC_Msg msg);
PPSMC_Result amdgpu_si_wait_for_smc_inactive(struct amdgpu_device *adev);
int amdgpu_si_load_smc_ucode(struct amdgpu_device *adev, u32 limit);
int amdgpu_si_read_smc_sram_dword(struct amdgpu_device *adev, u32 smc_address,
u32 *value, u32 limit);
int amdgpu_si_write_smc_sram_dword(struct amdgpu_device *adev, u32 smc_address,
u32 value, u32 limit);
#endif

View File

@@ -0,0 +1,33 @@
#
# Copyright 2017 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.
#
#
# Makefile for the 'smu manager' sub-component of powerplay.
# It provides the smu management services for the driver.
SMU_MGR = smumgr.o smu8_smumgr.o tonga_smumgr.o fiji_smumgr.o \
polaris10_smumgr.o iceland_smumgr.o \
smu7_smumgr.o vega10_smumgr.o smu10_smumgr.o ci_smumgr.o \
vega12_smumgr.o vegam_smumgr.o smu9_smumgr.o vega20_smumgr.o
AMD_PP_SMUMGR = $(addprefix $(AMD_PP_PATH)/smumgr/,$(SMU_MGR))
AMD_POWERPLAY_FILES += $(AMD_PP_SMUMGR)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,76 @@
/*
* Copyright 2017 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.
*
*/
#ifndef _CI_SMUMANAGER_H_
#define _CI_SMUMANAGER_H_
#define SMU__NUM_SCLK_DPM_STATE 8
#define SMU__NUM_MCLK_DPM_LEVELS 6
#define SMU__NUM_LCLK_DPM_LEVELS 8
#define SMU__NUM_PCIE_DPM_LEVELS 8
#include "smu7_discrete.h"
#include <pp_endian.h>
#include "ppatomctrl.h"
struct ci_pt_defaults {
u8 svi_load_line_en;
u8 svi_load_line_vddc;
u8 tdc_vddc_throttle_release_limit_perc;
u8 tdc_mawt;
u8 tdc_waterfall_ctl;
u8 dte_ambient_temp_base;
u32 display_cac;
u32 bapm_temp_gradient;
u16 bapmti_r[SMU7_DTE_ITERATIONS * SMU7_DTE_SOURCES * SMU7_DTE_SINKS];
u16 bapmti_rc[SMU7_DTE_ITERATIONS * SMU7_DTE_SOURCES * SMU7_DTE_SINKS];
};
struct ci_mc_reg_entry {
uint32_t mclk_max;
uint32_t mc_data[SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE];
};
struct ci_mc_reg_table {
uint8_t last;
uint8_t num_entries;
uint16_t validflag;
struct ci_mc_reg_entry mc_reg_table_entry[MAX_AC_TIMING_ENTRIES];
SMU7_Discrete_MCRegisterAddress mc_reg_address[SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE];
};
struct ci_smumgr {
uint32_t soft_regs_start;
uint32_t dpm_table_start;
uint32_t mc_reg_table_start;
uint32_t fan_table_start;
uint32_t arb_table_start;
uint32_t ulv_setting_starts;
struct SMU7_Discrete_DpmTable smc_state_table;
struct SMU7_Discrete_PmFuses power_tune_table;
const struct ci_pt_defaults *power_tune_defaults;
SMU7_Discrete_MCRegisters mc_regs;
struct ci_mc_reg_table mc_reg_table;
};
#endif

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More