forked from luck/tmp_suning_uos_patched
drm/amd/powerplay: add iceland HW manager
This patch introduces the iceland HW manager of powerplay which includes HW manager, clockpowergating, thermal, and powertune. Signed-off-by: Huang Rui <ray.huang@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
d550df0b60
commit
025f8bfb84
|
@ -10,7 +10,9 @@ HARDWARE_MGR = hwmgr.o processpptables.o functiontables.o \
|
|||
fiji_powertune.o fiji_hwmgr.o tonga_clockpowergating.o \
|
||||
fiji_clockpowergating.o fiji_thermal.o \
|
||||
polaris10_hwmgr.o polaris10_powertune.o polaris10_thermal.o \
|
||||
polaris10_clockpowergating.o
|
||||
polaris10_clockpowergating.o iceland_hwmgr.o \
|
||||
iceland_clockpowergating.o iceland_thermal.o \
|
||||
iceland_powertune.o
|
||||
|
||||
AMD_PP_HWMGR = $(addprefix $(AMD_PP_PATH)/hwmgr/,$(HARDWARE_MGR))
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@ extern int cz_hwmgr_init(struct pp_hwmgr *hwmgr);
|
|||
extern int tonga_hwmgr_init(struct pp_hwmgr *hwmgr);
|
||||
extern int fiji_hwmgr_init(struct pp_hwmgr *hwmgr);
|
||||
extern int polaris10_hwmgr_init(struct pp_hwmgr *hwmgr);
|
||||
extern int iceland_hwmgr_init(struct pp_hwmgr *hwmgr);
|
||||
|
||||
int hwmgr_init(struct amd_pp_init *pp_init, struct pp_instance *handle)
|
||||
{
|
||||
|
@ -67,6 +68,9 @@ int hwmgr_init(struct amd_pp_init *pp_init, struct pp_instance *handle)
|
|||
break;
|
||||
case AMDGPU_FAMILY_VI:
|
||||
switch (hwmgr->chip_id) {
|
||||
case CHIP_TOPAZ:
|
||||
iceland_hwmgr_init(hwmgr);
|
||||
break;
|
||||
case CHIP_TONGA:
|
||||
tonga_hwmgr_init(hwmgr);
|
||||
break;
|
||||
|
|
119
drivers/gpu/drm/amd/powerplay/hwmgr/iceland_clockpowergating.c
Normal file
119
drivers/gpu/drm/amd/powerplay/hwmgr/iceland_clockpowergating.c
Normal file
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
* 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.
|
||||
*
|
||||
* Author: Huang Rui <ray.huang@amd.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "hwmgr.h"
|
||||
#include "iceland_clockpowergating.h"
|
||||
#include "ppsmc.h"
|
||||
#include "iceland_hwmgr.h"
|
||||
|
||||
int iceland_phm_powerdown_uvd(struct pp_hwmgr *hwmgr)
|
||||
{
|
||||
/* iceland does not have MM hardware block */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iceland_phm_powerup_uvd(struct pp_hwmgr *hwmgr)
|
||||
{
|
||||
/* iceland does not have MM hardware block */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iceland_phm_powerdown_vce(struct pp_hwmgr *hwmgr)
|
||||
{
|
||||
/* iceland does not have MM hardware block */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iceland_phm_powerup_vce(struct pp_hwmgr *hwmgr)
|
||||
{
|
||||
/* iceland does not have MM hardware block */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iceland_phm_set_asic_block_gating(struct pp_hwmgr *hwmgr, enum
|
||||
PHM_AsicBlock block, enum PHM_ClockGateSetting gating)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
switch (block) {
|
||||
case PHM_AsicBlock_UVD_MVC:
|
||||
case PHM_AsicBlock_UVD:
|
||||
case PHM_AsicBlock_UVD_HD:
|
||||
case PHM_AsicBlock_UVD_SD:
|
||||
if (gating == PHM_ClockGateSetting_StaticOff)
|
||||
ret = iceland_phm_powerdown_uvd(hwmgr);
|
||||
else
|
||||
ret = iceland_phm_powerup_uvd(hwmgr);
|
||||
break;
|
||||
case PHM_AsicBlock_GFX:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int iceland_phm_disable_clock_power_gating(struct pp_hwmgr *hwmgr)
|
||||
{
|
||||
struct iceland_hwmgr *data = (struct iceland_hwmgr *)(hwmgr->backend);
|
||||
|
||||
data->uvd_power_gated = false;
|
||||
data->vce_power_gated = false;
|
||||
|
||||
iceland_phm_powerup_uvd(hwmgr);
|
||||
iceland_phm_powerup_vce(hwmgr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iceland_phm_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate)
|
||||
{
|
||||
if (bgate) {
|
||||
iceland_update_uvd_dpm(hwmgr, true);
|
||||
iceland_phm_powerdown_uvd(hwmgr);
|
||||
} else {
|
||||
iceland_phm_powerup_uvd(hwmgr);
|
||||
iceland_update_uvd_dpm(hwmgr, false);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iceland_phm_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate)
|
||||
{
|
||||
if (bgate)
|
||||
return iceland_phm_powerdown_vce(hwmgr);
|
||||
else
|
||||
return iceland_phm_powerup_vce(hwmgr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iceland_phm_update_clock_gatings(struct pp_hwmgr *hwmgr,
|
||||
const uint32_t *msg_id)
|
||||
{
|
||||
/* iceland does not have MM hardware block */
|
||||
return 0;
|
||||
}
|
|
@ -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.
|
||||
*
|
||||
* Author: Huang Rui <ray.huang@amd.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _ICELAND_CLOCK_POWER_GATING_H_
|
||||
#define _ICELAND_CLOCK_POWER_GATING_H_
|
||||
|
||||
#include "iceland_hwmgr.h"
|
||||
#include "pp_asicblocks.h"
|
||||
|
||||
extern int iceland_phm_set_asic_block_gating(struct pp_hwmgr *hwmgr, enum PHM_AsicBlock block, enum PHM_ClockGateSetting gating);
|
||||
extern int iceland_phm_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate);
|
||||
extern int iceland_phm_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate);
|
||||
extern int iceland_phm_powerdown_uvd(struct pp_hwmgr *hwmgr);
|
||||
extern int iceland_phm_disable_clock_power_gating(struct pp_hwmgr *hwmgr);
|
||||
extern int iceland_phm_update_clock_gatings(struct pp_hwmgr *hwmgr, const uint32_t *msg_id);
|
||||
#endif /* _ICELAND_CLOCK_POWER_GATING_H_ */
|
5617
drivers/gpu/drm/amd/powerplay/hwmgr/iceland_hwmgr.c
Normal file
5617
drivers/gpu/drm/amd/powerplay/hwmgr/iceland_hwmgr.c
Normal file
File diff suppressed because it is too large
Load Diff
424
drivers/gpu/drm/amd/powerplay/hwmgr/iceland_hwmgr.h
Normal file
424
drivers/gpu/drm/amd/powerplay/hwmgr/iceland_hwmgr.h
Normal file
|
@ -0,0 +1,424 @@
|
|||
/*
|
||||
* 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.
|
||||
*
|
||||
* Author: Huang Rui <ray.huang@amd.com>
|
||||
*
|
||||
*/
|
||||
#ifndef ICELAND_HWMGR_H
|
||||
#define ICELAND_HWMGR_H
|
||||
|
||||
#include "hwmgr.h"
|
||||
#include "ppatomctrl.h"
|
||||
#include "ppinterrupt.h"
|
||||
#include "ppsmc.h"
|
||||
#include "iceland_powertune.h"
|
||||
#include "pp_endian.h"
|
||||
#include "smu71_discrete.h"
|
||||
|
||||
#define ICELAND_MAX_HARDWARE_POWERLEVELS 2
|
||||
#define ICELAND_DYNCLK_NUMBER_OF_TREND_COEFFICIENTS 15
|
||||
|
||||
struct iceland_performance_level {
|
||||
uint32_t memory_clock;
|
||||
uint32_t engine_clock;
|
||||
uint16_t pcie_gen;
|
||||
uint16_t pcie_lane;
|
||||
};
|
||||
|
||||
struct _phw_iceland_bacos {
|
||||
uint32_t best_match;
|
||||
uint32_t baco_flags;
|
||||
struct iceland_performance_level performance_level;
|
||||
};
|
||||
typedef struct _phw_iceland_bacos phw_iceland_bacos;
|
||||
|
||||
struct _phw_iceland_uvd_clocks {
|
||||
uint32_t VCLK;
|
||||
uint32_t DCLK;
|
||||
};
|
||||
|
||||
typedef struct _phw_iceland_uvd_clocks phw_iceland_uvd_clocks;
|
||||
|
||||
struct _phw_iceland_vce_clocks {
|
||||
uint32_t EVCLK;
|
||||
uint32_t ECCLK;
|
||||
};
|
||||
|
||||
typedef struct _phw_iceland_vce_clocks phw_iceland_vce_clocks;
|
||||
|
||||
struct iceland_power_state {
|
||||
uint32_t magic;
|
||||
phw_iceland_uvd_clocks uvd_clocks;
|
||||
phw_iceland_vce_clocks vce_clocks;
|
||||
uint32_t sam_clk;
|
||||
uint32_t acp_clk;
|
||||
uint16_t performance_level_count;
|
||||
bool dc_compatible;
|
||||
uint32_t sclk_threshold;
|
||||
struct iceland_performance_level performance_levels[ICELAND_MAX_HARDWARE_POWERLEVELS];
|
||||
};
|
||||
|
||||
struct _phw_iceland_dpm_level {
|
||||
bool enabled;
|
||||
uint32_t value;
|
||||
uint32_t param1;
|
||||
};
|
||||
typedef struct _phw_iceland_dpm_level phw_iceland_dpm_level;
|
||||
|
||||
#define ICELAND_MAX_DEEPSLEEP_DIVIDER_ID 5
|
||||
#define MAX_REGULAR_DPM_NUMBER 8
|
||||
#define ICELAND_MINIMUM_ENGINE_CLOCK 5000
|
||||
|
||||
struct iceland_single_dpm_table {
|
||||
uint32_t count;
|
||||
phw_iceland_dpm_level dpm_levels[MAX_REGULAR_DPM_NUMBER];
|
||||
};
|
||||
|
||||
struct iceland_dpm_table {
|
||||
struct iceland_single_dpm_table sclk_table;
|
||||
struct iceland_single_dpm_table mclk_table;
|
||||
struct iceland_single_dpm_table pcie_speed_table;
|
||||
struct iceland_single_dpm_table vddc_table;
|
||||
struct iceland_single_dpm_table vdd_gfx_table;
|
||||
struct iceland_single_dpm_table vdd_ci_table;
|
||||
struct iceland_single_dpm_table mvdd_table;
|
||||
};
|
||||
typedef struct _phw_iceland_dpm_table phw_iceland_dpm_table;
|
||||
|
||||
|
||||
struct _phw_iceland_clock_regisiters {
|
||||
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;
|
||||
};
|
||||
typedef struct _phw_iceland_clock_regisiters phw_iceland_clock_registers;
|
||||
|
||||
struct _phw_iceland_voltage_smio_registers {
|
||||
uint32_t vs0_vid_lower_smio_cntl;
|
||||
};
|
||||
typedef struct _phw_iceland_voltage_smio_registers phw_iceland_voltage_smio_registers;
|
||||
|
||||
|
||||
struct _phw_iceland_mc_reg_entry {
|
||||
uint32_t mclk_max;
|
||||
uint32_t mc_data[SMU71_DISCRETE_MC_REGISTER_ARRAY_SIZE];
|
||||
};
|
||||
typedef struct _phw_iceland_mc_reg_entry phw_iceland_mc_reg_entry;
|
||||
|
||||
struct _phw_iceland_mc_reg_table {
|
||||
uint8_t last; /* number of registers*/
|
||||
uint8_t num_entries; /* number of entries in mc_reg_table_entry used*/
|
||||
uint16_t validflag; /* indicate the corresponding register is valid or not. 1: valid, 0: invalid. bit0->address[0], bit1->address[1], etc.*/
|
||||
phw_iceland_mc_reg_entry mc_reg_table_entry[MAX_AC_TIMING_ENTRIES];
|
||||
SMU71_Discrete_MCRegisterAddress mc_reg_address[SMU71_DISCRETE_MC_REGISTER_ARRAY_SIZE];
|
||||
};
|
||||
typedef struct _phw_iceland_mc_reg_table phw_iceland_mc_reg_table;
|
||||
|
||||
#define DISABLE_MC_LOADMICROCODE 1
|
||||
#define DISABLE_MC_CFGPROGRAMMING 2
|
||||
|
||||
|
||||
/*Ultra Low Voltage parameter structure */
|
||||
struct phw_iceland_ulv_parm{
|
||||
bool ulv_supported;
|
||||
uint32_t ch_ulv_parameter;
|
||||
uint32_t ulv_volt_change_delay;
|
||||
struct iceland_performance_level ulv_power_level;
|
||||
};
|
||||
|
||||
#define ICELAND_MAX_LEAKAGE_COUNT 8
|
||||
|
||||
struct phw_iceland_leakage_voltage {
|
||||
uint16_t count;
|
||||
uint16_t leakage_id[ICELAND_MAX_LEAKAGE_COUNT];
|
||||
uint16_t actual_voltage[ICELAND_MAX_LEAKAGE_COUNT];
|
||||
};
|
||||
|
||||
struct _phw_iceland_display_timing {
|
||||
uint32_t min_clock_insr;
|
||||
uint32_t num_existing_displays;
|
||||
};
|
||||
typedef struct _phw_iceland_display_timing phw_iceland_display_timing;
|
||||
|
||||
|
||||
struct phw_iceland_thermal_temperature_setting
|
||||
{
|
||||
long temperature_low;
|
||||
long temperature_high;
|
||||
long temperature_shutdown;
|
||||
};
|
||||
|
||||
struct _phw_iceland_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;
|
||||
};
|
||||
typedef struct _phw_iceland_dpmlevel_enable_mask phw_iceland_dpmlevel_enable_mask;
|
||||
|
||||
struct _phw_iceland_pcie_perf_range {
|
||||
uint16_t max;
|
||||
uint16_t min;
|
||||
};
|
||||
typedef struct _phw_iceland_pcie_perf_range phw_iceland_pcie_perf_range;
|
||||
|
||||
struct _phw_iceland_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;
|
||||
};
|
||||
typedef struct _phw_iceland_vbios_boot_state phw_iceland_vbios_boot_state;
|
||||
|
||||
#define DPMTABLE_OD_UPDATE_SCLK 0x00000001
|
||||
#define DPMTABLE_OD_UPDATE_MCLK 0x00000002
|
||||
#define DPMTABLE_UPDATE_SCLK 0x00000004
|
||||
#define DPMTABLE_UPDATE_MCLK 0x00000008
|
||||
|
||||
/* We need to review which fields are needed. */
|
||||
/* This is mostly a copy of the RV7xx/Evergreen structure which is close, but not identical to the N.Islands one. */
|
||||
struct iceland_hwmgr {
|
||||
struct iceland_dpm_table dpm_table;
|
||||
struct iceland_dpm_table golden_dpm_table;
|
||||
|
||||
uint32_t voting_rights_clients0;
|
||||
uint32_t voting_rights_clients1;
|
||||
uint32_t voting_rights_clients2;
|
||||
uint32_t voting_rights_clients3;
|
||||
uint32_t voting_rights_clients4;
|
||||
uint32_t voting_rights_clients5;
|
||||
uint32_t voting_rights_clients6;
|
||||
uint32_t voting_rights_clients7;
|
||||
uint32_t static_screen_threshold_unit;
|
||||
uint32_t static_screen_threshold;
|
||||
uint32_t voltage_control;
|
||||
uint32_t vdd_gfx_control;
|
||||
|
||||
uint32_t vddc_vddci_delta;
|
||||
uint32_t vddc_vddgfx_delta;
|
||||
|
||||
struct pp_interrupt_registration_info internal_high_thermal_interrupt_info;
|
||||
struct pp_interrupt_registration_info internal_low_thermal_interrupt_info;
|
||||
struct pp_interrupt_registration_info smc_to_host_interrupt_info;
|
||||
uint32_t active_auto_throttle_sources;
|
||||
|
||||
struct pp_interrupt_registration_info external_throttle_interrupt;
|
||||
irq_handler_func_t external_throttle_callback;
|
||||
void *external_throttle_context;
|
||||
|
||||
struct pp_interrupt_registration_info ctf_interrupt_info;
|
||||
irq_handler_func_t ctf_callback;
|
||||
void *ctf_context;
|
||||
|
||||
phw_iceland_clock_registers clock_registers;
|
||||
phw_iceland_voltage_smio_registers voltage_smio_registers;
|
||||
|
||||
bool is_memory_GDDR5;
|
||||
uint16_t acpi_vddc;
|
||||
bool pspp_notify_required; /* Flag to indicate if PSPP notification to SBIOS is required */
|
||||
uint16_t force_pcie_gen; /* The forced PCI-E speed if not 0xffff */
|
||||
uint16_t acpi_pcie_gen; /* The PCI-E speed at ACPI time */
|
||||
uint32_t pcie_gen_cap; /* The PCI-E speed capabilities bitmap from CAIL */
|
||||
uint32_t pcie_lane_cap; /* The PCI-E lane capabilities bitmap from CAIL */
|
||||
uint32_t pcie_spc_cap; /* Symbol Per Clock Capabilities from registry */
|
||||
struct phw_iceland_leakage_voltage vddc_leakage; /* The Leakage VDDC supported (based on leakage ID).*/
|
||||
struct phw_iceland_leakage_voltage vddcgfx_leakage; /* The Leakage VDDC supported (based on leakage ID). */
|
||||
struct phw_iceland_leakage_voltage vddci_leakage; /* The Leakage VDDCI supported (based on leakage ID). */
|
||||
|
||||
uint32_t mvdd_control;
|
||||
uint32_t vddc_mask_low;
|
||||
uint32_t mvdd_mask_low;
|
||||
uint16_t max_vddc_in_pp_table; /* the maximum VDDC value in the powerplay table*/
|
||||
uint16_t min_vddc_in_pp_table;
|
||||
uint16_t max_vddci_in_pp_table; /* the maximum VDDCI value in the powerplay table */
|
||||
uint16_t min_vddci_in_pp_table;
|
||||
uint32_t mclk_strobe_mode_threshold;
|
||||
uint32_t mclk_stutter_mode_threshold;
|
||||
uint32_t mclk_edc_enable_threshold;
|
||||
uint32_t mclk_edc_wr_enable_threshold;
|
||||
bool is_uvd_enabled;
|
||||
bool is_xdma_enabled;
|
||||
phw_iceland_vbios_boot_state vbios_boot_state;
|
||||
|
||||
bool battery_state;
|
||||
bool is_tlu_enabled;
|
||||
bool pcie_performance_request;
|
||||
|
||||
/* -------------- SMC SRAM Address of firmware header tables ----------------*/
|
||||
uint32_t sram_end; /* The first address after the SMC SRAM. */
|
||||
uint32_t dpm_table_start; /* The start of the dpm table in the SMC SRAM. */
|
||||
uint32_t soft_regs_start; /* The start of the soft registers in the SMC SRAM. */
|
||||
uint32_t mc_reg_table_start; /* The start of the mc register table in the SMC SRAM. */
|
||||
uint32_t fan_table_start; /* The start of the fan table in the SMC SRAM. */
|
||||
uint32_t arb_table_start; /* The start of the ARB setting table in the SMC SRAM. */
|
||||
uint32_t ulv_settings_start;
|
||||
SMU71_Discrete_DpmTable smc_state_table; /* The carbon copy of the SMC state table. */
|
||||
SMU71_Discrete_MCRegisters mc_reg_table;
|
||||
SMU71_Discrete_Ulv ulv_setting; /* The carbon copy of ULV setting. */
|
||||
|
||||
/* -------------- Stuff originally coming from Evergreen --------------------*/
|
||||
phw_iceland_mc_reg_table iceland_mc_reg_table;
|
||||
uint32_t vdd_ci_control;
|
||||
pp_atomctrl_voltage_table vddc_voltage_table;
|
||||
pp_atomctrl_voltage_table vddci_voltage_table;
|
||||
pp_atomctrl_voltage_table vddgfx_voltage_table;
|
||||
pp_atomctrl_voltage_table mvdd_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_vdd_ci;
|
||||
uint8_t mvdd_high_index;
|
||||
uint8_t mvdd_low_index;
|
||||
bool dll_defaule_on;
|
||||
bool performance_request_registered;
|
||||
|
||||
/* ----------------- Low Power Features ---------------------*/
|
||||
phw_iceland_bacos bacos;
|
||||
struct phw_iceland_ulv_parm ulv;
|
||||
|
||||
/* ----------------- CAC Stuff ---------------------*/
|
||||
uint32_t cac_table_start;
|
||||
bool cac_configuration_required; /* TRUE if PP_CACConfigurationRequired == 1 */
|
||||
bool driver_calculate_cac_leakage; /* TRUE if PP_DriverCalculateCACLeakage == 1 */
|
||||
bool cac_enabled;
|
||||
|
||||
/* ----------------- DPM2 Parameters ---------------------*/
|
||||
uint32_t power_containment_features;
|
||||
bool enable_bapm_feature;
|
||||
bool enable_dte_feature;
|
||||
bool enable_tdc_limit_feature;
|
||||
bool enable_pkg_pwr_tracking_feature;
|
||||
bool disable_uvd_power_tune_feature;
|
||||
struct iceland_pt_defaults *power_tune_defaults;
|
||||
SMU71_Discrete_PmFuses power_tune_table;
|
||||
uint32_t ul_dte_tj_offset; /* Fudge factor in DPM table to correct HW DTE errors */
|
||||
uint32_t fast_watermark_threshold; /* use fast watermark if clock is equal or above this. In percentage of the target high sclk. */
|
||||
|
||||
/* ----------------- Phase Shedding ---------------------*/
|
||||
bool vddc_phase_shed_control;
|
||||
|
||||
/* --------------------- DI/DT --------------------------*/
|
||||
phw_iceland_display_timing display_timing;
|
||||
|
||||
/* --------- ReadRegistry data for memory and engine clock margins ---- */
|
||||
uint32_t engine_clock_data;
|
||||
uint32_t memory_clock_data;
|
||||
|
||||
/* -------- Thermal Temperature Setting --------------*/
|
||||
struct phw_iceland_thermal_temperature_setting thermal_temp_setting;
|
||||
phw_iceland_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;
|
||||
/* used to store the previous dal min sclock */
|
||||
uint32_t min_engine_clocks;
|
||||
phw_iceland_pcie_perf_range pcie_gen_performance;
|
||||
phw_iceland_pcie_perf_range pcie_lane_performance;
|
||||
phw_iceland_pcie_perf_range pcie_gen_power_saving;
|
||||
phw_iceland_pcie_perf_range pcie_lane_power_saving;
|
||||
bool use_pcie_performance_levels;
|
||||
bool use_pcie_power_saving_levels;
|
||||
/* percentage value from 0-100, default 50 */
|
||||
uint32_t activity_target[SMU71_MAX_LEVELS_GRAPHICS];
|
||||
uint32_t mclk_activity_target;
|
||||
uint32_t low_sclk_interrupt_threshold;
|
||||
uint32_t last_mclk_dpm_enable_mask;
|
||||
bool uvd_enabled;
|
||||
uint32_t pcc_monitor_enabled;
|
||||
|
||||
/* --------- Power Gating States ------------*/
|
||||
bool uvd_power_gated; /* 1: gated, 0:not gated */
|
||||
bool vce_power_gated; /* 1: gated, 0:not gated */
|
||||
bool samu_power_gated; /* 1: gated, 0:not gated */
|
||||
bool acp_power_gated; /* 1: gated, 0:not gated */
|
||||
bool pg_acp_init;
|
||||
|
||||
/* soft pptable for re-uploading into smu */
|
||||
void *soft_pp_table;
|
||||
};
|
||||
|
||||
typedef struct iceland_hwmgr iceland_hwmgr;
|
||||
|
||||
int iceland_hwmgr_init(struct pp_hwmgr *hwmgr);
|
||||
int iceland_update_uvd_dpm(struct pp_hwmgr *hwmgr, bool bgate);
|
||||
uint32_t iceland_get_xclk(struct pp_hwmgr *hwmgr);
|
||||
int iceland_populate_bapm_vddc_vid_sidd(struct pp_hwmgr *hwmgr);
|
||||
int iceland_populate_vddc_vid(struct pp_hwmgr *hwmgr);
|
||||
|
||||
#define ICELAND_DPM2_NEAR_TDP_DEC 10
|
||||
#define ICELAND_DPM2_ABOVE_SAFE_INC 5
|
||||
#define ICELAND_DPM2_BELOW_SAFE_INC 20
|
||||
|
||||
/*
|
||||
* Log2 of the LTA window size (l2numWin_TDP). Eg. If LTA windows size
|
||||
* is 128, then this value should be Log2(128) = 7.
|
||||
*/
|
||||
#define ICELAND_DPM2_LTA_WINDOW_SIZE 7
|
||||
|
||||
#define ICELAND_DPM2_LTS_TRUNCATE 0
|
||||
|
||||
#define ICELAND_DPM2_TDP_SAFE_LIMIT_PERCENT 80 // Maximum 100
|
||||
|
||||
#define ICELAND_DPM2_MAXPS_PERCENT_H 90 // Maximum 0xFF
|
||||
#define ICELAND_DPM2_MAXPS_PERCENT_M 90 // Maximum 0xFF
|
||||
|
||||
#define ICELAND_DPM2_PWREFFICIENCYRATIO_MARGIN 50
|
||||
|
||||
#define ICELAND_DPM2_SQ_RAMP_MAX_POWER 0x3FFF
|
||||
#define ICELAND_DPM2_SQ_RAMP_MIN_POWER 0x12
|
||||
#define ICELAND_DPM2_SQ_RAMP_MAX_POWER_DELTA 0x15
|
||||
#define ICELAND_DPM2_SQ_RAMP_SHORT_TERM_INTERVAL_SIZE 0x1E
|
||||
#define ICELAND_DPM2_SQ_RAMP_LONG_TERM_INTERVAL_RATIO 0xF
|
||||
|
||||
#define ICELAND_VOLTAGE_CONTROL_NONE 0x0
|
||||
#define ICELAND_VOLTAGE_CONTROL_BY_GPIO 0x1
|
||||
#define ICELAND_VOLTAGE_CONTROL_BY_SVID2 0x2
|
||||
|
||||
/* convert to Q8.8 format for firmware */
|
||||
#define ICELAND_Q88_FORMAT_CONVERSION_UNIT 256
|
||||
|
||||
#define ICELAND_UNUSED_GPIO_PIN 0x7F
|
||||
|
||||
#endif
|
491
drivers/gpu/drm/amd/powerplay/hwmgr/iceland_powertune.c
Normal file
491
drivers/gpu/drm/amd/powerplay/hwmgr/iceland_powertune.c
Normal file
|
@ -0,0 +1,491 @@
|
|||
/*
|
||||
* 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.
|
||||
*
|
||||
* Author: Huang Rui <ray.huang@amd.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "amdgpu.h"
|
||||
#include "hwmgr.h"
|
||||
#include "smumgr.h"
|
||||
#include "iceland_hwmgr.h"
|
||||
#include "iceland_powertune.h"
|
||||
#include "iceland_smumgr.h"
|
||||
#include "smu71_discrete.h"
|
||||
#include "smu71.h"
|
||||
#include "pp_debug.h"
|
||||
#include "cgs_common.h"
|
||||
#include "pp_endian.h"
|
||||
|
||||
#include "bif/bif_5_0_d.h"
|
||||
#include "bif/bif_5_0_sh_mask.h"
|
||||
|
||||
#define VOLTAGE_SCALE 4
|
||||
#define POWERTUNE_DEFAULT_SET_MAX 1
|
||||
|
||||
#define DEVICE_ID_VI_ICELAND_M_6900 0x6900
|
||||
#define DEVICE_ID_VI_ICELAND_M_6901 0x6901
|
||||
#define DEVICE_ID_VI_ICELAND_M_6902 0x6902
|
||||
#define DEVICE_ID_VI_ICELAND_M_6903 0x6903
|
||||
|
||||
|
||||
struct iceland_pt_defaults defaults_iceland =
|
||||
{
|
||||
/*
|
||||
* sviLoadLIneEn, SviLoadLineVddC, TDC_VDDC_ThrottleReleaseLimitPerc,
|
||||
* TDC_MAWt, TdcWaterfallCtl, DTEAmbientTempBase, DisplayCac, BAPM_TEMP_GRADIENT
|
||||
*/
|
||||
1, 0xF, 0xFD, 0x19, 5, 45, 0, 0xB0000,
|
||||
{ 0x79, 0x253, 0x25D, 0xAE, 0x72, 0x80, 0x83, 0x86, 0x6F, 0xC8, 0xC9, 0xC9, 0x2F, 0x4D, 0x61 },
|
||||
{ 0x17C, 0x172, 0x180, 0x1BC, 0x1B3, 0x1BD, 0x206, 0x200, 0x203, 0x25D, 0x25A, 0x255, 0x2C3, 0x2C5, 0x2B4 }
|
||||
};
|
||||
|
||||
/* 35W - XT, XTL */
|
||||
struct iceland_pt_defaults defaults_icelandxt =
|
||||
{
|
||||
/*
|
||||
* sviLoadLIneEn, SviLoadLineVddC,
|
||||
* TDC_VDDC_ThrottleReleaseLimitPerc, TDC_MAWt,
|
||||
* TdcWaterfallCtl, DTEAmbientTempBase, DisplayCac,
|
||||
* BAPM_TEMP_GRADIENT
|
||||
*/
|
||||
1, 0xF, 0xFD, 0x19, 5, 45, 0, 0x0,
|
||||
{ 0xA7, 0x0, 0x0, 0xB5, 0x0, 0x0, 0x9F, 0x0, 0x0, 0xD6, 0x0, 0x0, 0xD7, 0x0, 0x0},
|
||||
{ 0x1EA, 0x0, 0x0, 0x224, 0x0, 0x0, 0x25E, 0x0, 0x0, 0x28E, 0x0, 0x0, 0x2AB, 0x0, 0x0}
|
||||
};
|
||||
|
||||
/* 25W - PRO, LE */
|
||||
struct iceland_pt_defaults defaults_icelandpro =
|
||||
{
|
||||
/*
|
||||
* sviLoadLIneEn, SviLoadLineVddC,
|
||||
* TDC_VDDC_ThrottleReleaseLimitPerc, TDC_MAWt,
|
||||
* TdcWaterfallCtl, DTEAmbientTempBase, DisplayCac,
|
||||
* BAPM_TEMP_GRADIENT
|
||||
*/
|
||||
1, 0xF, 0xFD, 0x19, 5, 45, 0, 0x0,
|
||||
{ 0xB7, 0x0, 0x0, 0xC3, 0x0, 0x0, 0xB5, 0x0, 0x0, 0xEA, 0x0, 0x0, 0xE6, 0x0, 0x0},
|
||||
{ 0x1EA, 0x0, 0x0, 0x224, 0x0, 0x0, 0x25E, 0x0, 0x0, 0x28E, 0x0, 0x0, 0x2AB, 0x0, 0x0}
|
||||
};
|
||||
|
||||
void iceland_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr)
|
||||
{
|
||||
struct iceland_hwmgr *data = (struct iceland_hwmgr *)(hwmgr->backend);
|
||||
uint32_t tmp = 0;
|
||||
struct cgs_system_info sys_info = {0};
|
||||
uint32_t pdev_id;
|
||||
|
||||
sys_info.size = sizeof(struct cgs_system_info);
|
||||
sys_info.info_id = CGS_SYSTEM_INFO_PCIE_DEV;
|
||||
cgs_query_system_info(hwmgr->device, &sys_info);
|
||||
pdev_id = (uint32_t)sys_info.value;
|
||||
|
||||
switch (pdev_id) {
|
||||
case DEVICE_ID_VI_ICELAND_M_6900:
|
||||
case DEVICE_ID_VI_ICELAND_M_6903:
|
||||
data->power_tune_defaults = &defaults_icelandxt;
|
||||
break;
|
||||
|
||||
case DEVICE_ID_VI_ICELAND_M_6901:
|
||||
case DEVICE_ID_VI_ICELAND_M_6902:
|
||||
data->power_tune_defaults = &defaults_icelandpro;
|
||||
break;
|
||||
default:
|
||||
/* TODO: need to assign valid defaults */
|
||||
data->power_tune_defaults = &defaults_iceland;
|
||||
pr_warning("Unknown V.I. Device ID.\n");
|
||||
break;
|
||||
}
|
||||
|
||||
/* Assume disabled */
|
||||
phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
|
||||
PHM_PlatformCaps_PowerContainment);
|
||||
phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
|
||||
PHM_PlatformCaps_CAC);
|
||||
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);
|
||||
|
||||
data->ul_dte_tj_offset = tmp;
|
||||
|
||||
if (!tmp) {
|
||||
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
|
||||
PHM_PlatformCaps_CAC);
|
||||
|
||||
data->fast_watermark_threshold = 100;
|
||||
|
||||
if (hwmgr->powercontainment_enabled) {
|
||||
phm_cap_set(hwmgr->platform_descriptor.platformCaps,
|
||||
PHM_PlatformCaps_PowerContainment);
|
||||
tmp = 1;
|
||||
data->enable_dte_feature = tmp ? false : true;
|
||||
data->enable_tdc_limit_feature = tmp ? true : false;
|
||||
data->enable_pkg_pwr_tracking_feature = tmp ? true : false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int iceland_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr)
|
||||
{
|
||||
struct iceland_hwmgr *data = (struct iceland_hwmgr *)(hwmgr->backend);
|
||||
struct iceland_pt_defaults *defaults = data->power_tune_defaults;
|
||||
SMU71_Discrete_DpmTable *dpm_table = &(data->smc_state_table);
|
||||
struct phm_cac_tdp_table *cac_dtp_table = hwmgr->dyn_state.cac_dtp_table;
|
||||
struct phm_ppm_table *ppm = hwmgr->dyn_state.ppm_parameter_table;
|
||||
uint16_t *def1, *def2;
|
||||
int i, j, k;
|
||||
|
||||
/*
|
||||
* TDP number of fraction bits are changed from 8 to 7 for Iceland
|
||||
* as requested by SMC team
|
||||
*/
|
||||
dpm_table->DefaultTdp = PP_HOST_TO_SMC_US((uint16_t)(cac_dtp_table->usTDP * 256));
|
||||
dpm_table->TargetTdp = PP_HOST_TO_SMC_US((uint16_t)(cac_dtp_table->usConfigurableTDP * 256));
|
||||
|
||||
dpm_table->DTETjOffset = (uint8_t)data->ul_dte_tj_offset;
|
||||
|
||||
dpm_table->GpuTjMax = (uint8_t)(data->thermal_temp_setting.temperature_high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES);
|
||||
dpm_table->GpuTjHyst = 8;
|
||||
|
||||
dpm_table->DTEAmbientTempBase = defaults->dte_ambient_temp_base;
|
||||
|
||||
/* The following are for new Iceland Multi-input fan/thermal control */
|
||||
if(NULL != ppm) {
|
||||
dpm_table->PPM_PkgPwrLimit = (uint16_t)ppm->dgpu_tdp * 256 / 1000;
|
||||
dpm_table->PPM_TemperatureLimit = (uint16_t)ppm->tj_max * 256;
|
||||
} else {
|
||||
dpm_table->PPM_PkgPwrLimit = 0;
|
||||
dpm_table->PPM_TemperatureLimit = 0;
|
||||
}
|
||||
|
||||
CONVERT_FROM_HOST_TO_SMC_US(dpm_table->PPM_PkgPwrLimit);
|
||||
CONVERT_FROM_HOST_TO_SMC_US(dpm_table->PPM_TemperatureLimit);
|
||||
|
||||
dpm_table->BAPM_TEMP_GRADIENT = PP_HOST_TO_SMC_UL(defaults->bamp_temp_gradient);
|
||||
def1 = defaults->bapmti_r;
|
||||
def2 = defaults->bapmti_rc;
|
||||
|
||||
for (i = 0; i < SMU71_DTE_ITERATIONS; i++) {
|
||||
for (j = 0; j < SMU71_DTE_SOURCES; j++) {
|
||||
for (k = 0; k < SMU71_DTE_SINKS; k++) {
|
||||
dpm_table->BAPMTI_R[i][j][k] = PP_HOST_TO_SMC_US(*def1);
|
||||
dpm_table->BAPMTI_RC[i][j][k] = PP_HOST_TO_SMC_US(*def2);
|
||||
def1++;
|
||||
def2++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iceland_populate_svi_load_line(struct pp_hwmgr *hwmgr)
|
||||
{
|
||||
struct iceland_hwmgr *data = (struct iceland_hwmgr *)(hwmgr->backend);
|
||||
const struct iceland_pt_defaults *defaults = data->power_tune_defaults;
|
||||
|
||||
data->power_tune_table.SviLoadLineEn = defaults->svi_load_line_en;
|
||||
data->power_tune_table.SviLoadLineVddC = defaults->svi_load_line_vddc;
|
||||
data->power_tune_table.SviLoadLineTrimVddC = 3;
|
||||
data->power_tune_table.SviLoadLineOffsetVddC = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iceland_populate_tdc_limit(struct pp_hwmgr *hwmgr)
|
||||
{
|
||||
uint16_t tdc_limit;
|
||||
struct iceland_hwmgr *data = (struct iceland_hwmgr *)(hwmgr->backend);
|
||||
const struct iceland_pt_defaults *defaults = data->power_tune_defaults;
|
||||
|
||||
/* TDC number of fraction bits are changed from 8 to 7
|
||||
* for Iceland as requested by SMC team
|
||||
*/
|
||||
tdc_limit = (uint16_t)(hwmgr->dyn_state.cac_dtp_table->usTDC * 256);
|
||||
data->power_tune_table.TDC_VDDC_PkgLimit =
|
||||
CONVERT_FROM_HOST_TO_SMC_US(tdc_limit);
|
||||
data->power_tune_table.TDC_VDDC_ThrottleReleaseLimitPerc =
|
||||
defaults->tdc_vddc_throttle_release_limit_perc;
|
||||
data->power_tune_table.TDC_MAWt = defaults->tdc_mawt;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iceland_populate_dw8(struct pp_hwmgr *hwmgr, uint32_t fuse_table_offset)
|
||||
{
|
||||
struct iceland_hwmgr *data = (struct iceland_hwmgr *)(hwmgr->backend);
|
||||
const struct iceland_pt_defaults *defaults = data->power_tune_defaults;
|
||||
uint32_t temp;
|
||||
|
||||
if (iceland_read_smc_sram_dword(hwmgr->smumgr,
|
||||
fuse_table_offset +
|
||||
offsetof(SMU71_Discrete_PmFuses, TdcWaterfallCtl),
|
||||
(uint32_t *)&temp, data->sram_end))
|
||||
PP_ASSERT_WITH_CODE(false,
|
||||
"Attempt to read PmFuses.DW6 (SviLoadLineEn) from SMC Failed!",
|
||||
return -EINVAL);
|
||||
else
|
||||
data->power_tune_table.TdcWaterfallCtl = defaults->tdc_waterfall_ctl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iceland_populate_temperature_scaler(struct pp_hwmgr *hwmgr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iceland_populate_gnb_lpml(struct pp_hwmgr *hwmgr)
|
||||
{
|
||||
int i;
|
||||
struct iceland_hwmgr *data = (struct iceland_hwmgr *)(hwmgr->backend);
|
||||
|
||||
/* Currently not used. Set all to zero. */
|
||||
for (i = 0; i < 8; i++)
|
||||
data->power_tune_table.GnbLPML[i] = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iceland_min_max_vgnb_lpml_id_from_bapm_vddc(struct pp_hwmgr *hwmgr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iceland_populate_bapm_vddc_base_leakage_sidd(struct pp_hwmgr *hwmgr)
|
||||
{
|
||||
struct iceland_hwmgr *data = (struct iceland_hwmgr *)(hwmgr->backend);
|
||||
uint16_t HiSidd = data->power_tune_table.BapmVddCBaseLeakageHiSidd;
|
||||
uint16_t LoSidd = data->power_tune_table.BapmVddCBaseLeakageLoSidd;
|
||||
struct phm_cac_tdp_table *cac_table = hwmgr->dyn_state.cac_dtp_table;
|
||||
|
||||
HiSidd = (uint16_t)(cac_table->usHighCACLeakage / 100 * 256);
|
||||
LoSidd = (uint16_t)(cac_table->usLowCACLeakage / 100 * 256);
|
||||
|
||||
data->power_tune_table.BapmVddCBaseLeakageHiSidd =
|
||||
CONVERT_FROM_HOST_TO_SMC_US(HiSidd);
|
||||
data->power_tune_table.BapmVddCBaseLeakageLoSidd =
|
||||
CONVERT_FROM_HOST_TO_SMC_US(LoSidd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iceland_populate_pm_fuses(struct pp_hwmgr *hwmgr)
|
||||
{
|
||||
struct iceland_hwmgr *data = (struct iceland_hwmgr *)(hwmgr->backend);
|
||||
uint32_t pm_fuse_table_offset;
|
||||
|
||||
if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
|
||||
PHM_PlatformCaps_PowerContainment)) {
|
||||
if (iceland_read_smc_sram_dword(hwmgr->smumgr,
|
||||
SMU71_FIRMWARE_HEADER_LOCATION +
|
||||
offsetof(SMU71_Firmware_Header, PmFuseTable),
|
||||
&pm_fuse_table_offset, data->sram_end))
|
||||
PP_ASSERT_WITH_CODE(false,
|
||||
"Attempt to get pm_fuse_table_offset Failed!",
|
||||
return -EINVAL);
|
||||
|
||||
/* DW0 - DW3 */
|
||||
if (iceland_populate_bapm_vddc_vid_sidd(hwmgr))
|
||||
PP_ASSERT_WITH_CODE(false,
|
||||
"Attempt to populate bapm vddc vid Failed!",
|
||||
return -EINVAL);
|
||||
|
||||
/* DW4 - DW5 */
|
||||
if (iceland_populate_vddc_vid(hwmgr))
|
||||
PP_ASSERT_WITH_CODE(false,
|
||||
"Attempt to populate vddc vid Failed!",
|
||||
return -EINVAL);
|
||||
|
||||
/* DW6 */
|
||||
if (iceland_populate_svi_load_line(hwmgr))
|
||||
PP_ASSERT_WITH_CODE(false,
|
||||
"Attempt to populate SviLoadLine Failed!",
|
||||
return -EINVAL);
|
||||
/* DW7 */
|
||||
if (iceland_populate_tdc_limit(hwmgr))
|
||||
PP_ASSERT_WITH_CODE(false,
|
||||
"Attempt to populate TDCLimit Failed!", return -EINVAL);
|
||||
/* DW8 */
|
||||
if (iceland_populate_dw8(hwmgr, pm_fuse_table_offset))
|
||||
PP_ASSERT_WITH_CODE(false,
|
||||
"Attempt to populate TdcWaterfallCtl, "
|
||||
"LPMLTemperature Min and Max Failed!",
|
||||
return -EINVAL);
|
||||
|
||||
/* DW9-DW12 */
|
||||
if (0 != iceland_populate_temperature_scaler(hwmgr))
|
||||
PP_ASSERT_WITH_CODE(false,
|
||||
"Attempt to populate LPMLTemperatureScaler Failed!",
|
||||
return -EINVAL);
|
||||
|
||||
/* DW13-DW16 */
|
||||
if (iceland_populate_gnb_lpml(hwmgr))
|
||||
PP_ASSERT_WITH_CODE(false,
|
||||
"Attempt to populate GnbLPML Failed!",
|
||||
return -EINVAL);
|
||||
|
||||
/* DW17 */
|
||||
if (iceland_min_max_vgnb_lpml_id_from_bapm_vddc(hwmgr))
|
||||
PP_ASSERT_WITH_CODE(false,
|
||||
"Attempt to populate GnbLPML Min and Max Vid Failed!",
|
||||
return -EINVAL);
|
||||
|
||||
/* DW18 */
|
||||
if (iceland_populate_bapm_vddc_base_leakage_sidd(hwmgr))
|
||||
PP_ASSERT_WITH_CODE(false,
|
||||
"Attempt to populate BapmVddCBaseLeakage Hi and Lo Sidd Failed!",
|
||||
return -EINVAL);
|
||||
|
||||
if (iceland_copy_bytes_to_smc(hwmgr->smumgr, pm_fuse_table_offset,
|
||||
(uint8_t *)&data->power_tune_table,
|
||||
sizeof(struct SMU71_Discrete_PmFuses), data->sram_end))
|
||||
PP_ASSERT_WITH_CODE(false,
|
||||
"Attempt to download PmFuseTable Failed!",
|
||||
return -EINVAL);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iceland_enable_smc_cac(struct pp_hwmgr *hwmgr)
|
||||
{
|
||||
struct iceland_hwmgr *data = (struct iceland_hwmgr *)(hwmgr->backend);
|
||||
int result = 0;
|
||||
|
||||
if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
|
||||
PHM_PlatformCaps_CAC)) {
|
||||
int smc_result;
|
||||
smc_result = smum_send_msg_to_smc(hwmgr->smumgr,
|
||||
(uint16_t)(PPSMC_MSG_EnableCac));
|
||||
PP_ASSERT_WITH_CODE((0 == smc_result),
|
||||
"Failed to enable CAC in SMC.", result = -1);
|
||||
|
||||
data->cac_enabled = (0 == smc_result) ? true : false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static int iceland_set_power_limit(struct pp_hwmgr *hwmgr, uint32_t n)
|
||||
{
|
||||
struct iceland_hwmgr *data = (struct iceland_hwmgr *)(hwmgr->backend);
|
||||
|
||||
if(data->power_containment_features &
|
||||
POWERCONTAINMENT_FEATURE_PkgPwrLimit)
|
||||
return smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
|
||||
PPSMC_MSG_PkgPwrSetLimit, n);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iceland_set_overdriver_target_tdp(struct pp_hwmgr *pHwMgr, uint32_t target_tdp)
|
||||
{
|
||||
return smum_send_msg_to_smc_with_parameter(pHwMgr->smumgr,
|
||||
PPSMC_MSG_OverDriveSetTargetTdp, target_tdp);
|
||||
}
|
||||
|
||||
int iceland_enable_power_containment(struct pp_hwmgr *hwmgr)
|
||||
{
|
||||
struct iceland_hwmgr *data = (struct iceland_hwmgr *)(hwmgr->backend);
|
||||
SMU71_Discrete_DpmTable *dpm_table = &data->smc_state_table;
|
||||
int smc_result;
|
||||
int result = 0;
|
||||
uint32_t is_asic_kicker;
|
||||
|
||||
data->power_containment_features = 0;
|
||||
if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
|
||||
PHM_PlatformCaps_PowerContainment)) {
|
||||
is_asic_kicker = cgs_read_register(hwmgr->device, mmCC_BIF_BX_STRAP2);
|
||||
is_asic_kicker = (is_asic_kicker >> 12) & 0x01;
|
||||
|
||||
if (data->enable_bapm_feature &&
|
||||
(!is_asic_kicker ||
|
||||
phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
|
||||
PHM_PlatformCaps_DisableUsingActualTemperatureForPowerCalc))) {
|
||||
smc_result = smum_send_msg_to_smc(hwmgr->smumgr,
|
||||
(uint16_t)(PPSMC_MSG_EnableDTE));
|
||||
PP_ASSERT_WITH_CODE((0 == smc_result),
|
||||
"Failed to enable BAPM in SMC.", result = -1;);
|
||||
if (0 == smc_result)
|
||||
data->power_containment_features |= POWERCONTAINMENT_FEATURE_BAPM;
|
||||
}
|
||||
|
||||
if (is_asic_kicker && !phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
|
||||
PHM_PlatformCaps_DisableUsingActualTemperatureForPowerCalc))
|
||||
dpm_table->DTEMode = 2;
|
||||
|
||||
if (data->enable_tdc_limit_feature) {
|
||||
smc_result = smum_send_msg_to_smc(hwmgr->smumgr,
|
||||
(uint16_t)(PPSMC_MSG_TDCLimitEnable));
|
||||
PP_ASSERT_WITH_CODE((0 == smc_result),
|
||||
"Failed to enable TDCLimit in SMC.", result = -1;);
|
||||
if (0 == smc_result)
|
||||
data->power_containment_features |=
|
||||
POWERCONTAINMENT_FEATURE_TDCLimit;
|
||||
}
|
||||
|
||||
if (data->enable_pkg_pwr_tracking_feature) {
|
||||
smc_result = smum_send_msg_to_smc(hwmgr->smumgr,
|
||||
(uint16_t)(PPSMC_MSG_PkgPwrLimitEnable));
|
||||
PP_ASSERT_WITH_CODE((0 == smc_result),
|
||||
"Failed to enable PkgPwrTracking in SMC.", result = -1;);
|
||||
if (0 == smc_result) {
|
||||
struct phm_cac_tdp_table *cac_table =
|
||||
hwmgr->dyn_state.cac_dtp_table;
|
||||
uint32_t default_limit =
|
||||
(uint32_t)(cac_table->usMaximumPowerDeliveryLimit * 256);
|
||||
|
||||
data->power_containment_features |=
|
||||
POWERCONTAINMENT_FEATURE_PkgPwrLimit;
|
||||
|
||||
if (iceland_set_power_limit(hwmgr, default_limit))
|
||||
printk(KERN_ERR "Failed to set Default Power Limit in SMC!");
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int iceland_power_control_set_level(struct pp_hwmgr *hwmgr)
|
||||
{
|
||||
struct phm_cac_tdp_table *cac_table = hwmgr->dyn_state.cac_dtp_table;
|
||||
int adjust_percent, target_tdp;
|
||||
int result = 0;
|
||||
|
||||
if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
|
||||
PHM_PlatformCaps_PowerContainment)) {
|
||||
/* adjustment percentage has already been validated */
|
||||
adjust_percent = hwmgr->platform_descriptor.TDPAdjustmentPolarity ?
|
||||
hwmgr->platform_descriptor.TDPAdjustment :
|
||||
(-1 * hwmgr->platform_descriptor.TDPAdjustment);
|
||||
/*
|
||||
* SMC requested that target_tdp to be 7 bit fraction in DPM table
|
||||
* but message to be 8 bit fraction for messages
|
||||
*/
|
||||
target_tdp = ((100 + adjust_percent) * (int)(cac_table->usTDP * 256)) / 100;
|
||||
result = iceland_set_overdriver_target_tdp(hwmgr, (uint32_t)target_tdp);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
74
drivers/gpu/drm/amd/powerplay/hwmgr/iceland_powertune.h
Normal file
74
drivers/gpu/drm/amd/powerplay/hwmgr/iceland_powertune.h
Normal file
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* 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.
|
||||
*
|
||||
* Author: Huang Rui <ray.huang@amd.com>
|
||||
*
|
||||
*/
|
||||
#ifndef ICELAND_POWERTUNE_H
|
||||
#define ICELAND_POWERTUNE_H
|
||||
|
||||
#include "smu71.h"
|
||||
|
||||
enum iceland_pt_config_reg_type {
|
||||
ICELAND_CONFIGREG_MMR = 0,
|
||||
ICELAND_CONFIGREG_SMC_IND,
|
||||
ICELAND_CONFIGREG_DIDT_IND,
|
||||
ICELAND_CONFIGREG_CACHE,
|
||||
ICELAND_CONFIGREG_MAX
|
||||
};
|
||||
|
||||
/* PowerContainment Features */
|
||||
#define POWERCONTAINMENT_FEATURE_DTE 0x00000001
|
||||
#define POWERCONTAINMENT_FEATURE_TDCLimit 0x00000002
|
||||
#define POWERCONTAINMENT_FEATURE_PkgPwrLimit 0x00000004
|
||||
#define POWERCONTAINMENT_FEATURE_BAPM 0x00000001
|
||||
|
||||
struct iceland_pt_config_reg {
|
||||
uint32_t offset;
|
||||
uint32_t mask;
|
||||
uint32_t shift;
|
||||
uint32_t value;
|
||||
enum iceland_pt_config_reg_type type;
|
||||
};
|
||||
|
||||
struct iceland_pt_defaults
|
||||
{
|
||||
uint8_t svi_load_line_en;
|
||||
uint8_t svi_load_line_vddc;
|
||||
uint8_t tdc_vddc_throttle_release_limit_perc;
|
||||
uint8_t tdc_mawt;
|
||||
uint8_t tdc_waterfall_ctl;
|
||||
uint8_t dte_ambient_temp_base;
|
||||
uint32_t display_cac;
|
||||
uint32_t bamp_temp_gradient;
|
||||
uint16_t bapmti_r[SMU71_DTE_ITERATIONS * SMU71_DTE_SOURCES * SMU71_DTE_SINKS];
|
||||
uint16_t bapmti_rc[SMU71_DTE_ITERATIONS * SMU71_DTE_SOURCES * SMU71_DTE_SINKS];
|
||||
};
|
||||
|
||||
void iceland_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr);
|
||||
int iceland_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr);
|
||||
int iceland_populate_pm_fuses(struct pp_hwmgr *hwmgr);
|
||||
int iceland_enable_smc_cac(struct pp_hwmgr *hwmgr);
|
||||
int iceland_enable_power_containment(struct pp_hwmgr *hwmgr);
|
||||
int iceland_power_control_set_level(struct pp_hwmgr *hwmgr);
|
||||
|
||||
#endif /* ICELAND_POWERTUNE_H */
|
||||
|
595
drivers/gpu/drm/amd/powerplay/hwmgr/iceland_thermal.c
Normal file
595
drivers/gpu/drm/amd/powerplay/hwmgr/iceland_thermal.c
Normal file
|
@ -0,0 +1,595 @@
|
|||
/*
|
||||
* 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.
|
||||
*
|
||||
* Author: Huang Rui <ray.huang@amd.com>
|
||||
*
|
||||
*/
|
||||
#include <asm/div64.h>
|
||||
#include "iceland_thermal.h"
|
||||
#include "iceland_hwmgr.h"
|
||||
#include "iceland_smumgr.h"
|
||||
#include "atombios.h"
|
||||
#include "ppsmc.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 "smu/smu_7_1_1_d.h"
|
||||
#include "smu/smu_7_1_1_sh_mask.h"
|
||||
|
||||
|
||||
/**
|
||||
* Get Fan Speed Control Parameters.
|
||||
* @param hwmgr the address of the powerplay hardware manager.
|
||||
* @param pSpeed is the address of the structure where the result is to be placed.
|
||||
* @exception Always succeeds except if we cannot zero out the output structure.
|
||||
*/
|
||||
int iceland_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 (0 != 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Fan Speed in percent.
|
||||
* @param hwmgr the address of the powerplay hardware manager.
|
||||
* @param pSpeed is the address of the structure where the result is to be placed.
|
||||
* @exception Fails is the 100% setting appears to be 0.
|
||||
*/
|
||||
int iceland_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 0;
|
||||
|
||||
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 (0 == duty100)
|
||||
return -EINVAL;
|
||||
|
||||
|
||||
tmp64 = (uint64_t)duty * 100;
|
||||
do_div(tmp64, duty100);
|
||||
*speed = (uint32_t)tmp64;
|
||||
|
||||
if (*speed > 100)
|
||||
*speed = 100;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Fan Speed in RPM.
|
||||
* @param hwmgr the address of the powerplay hardware manager.
|
||||
* @param speed is the address of the structure where the result is to be placed.
|
||||
* @exception Returns not supported if no fan is found or if pulses per revolution are not set
|
||||
*/
|
||||
int iceland_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t *speed)
|
||||
{
|
||||
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 iceland_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.
|
||||
*/
|
||||
static int iceland_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 iceland_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr)
|
||||
{
|
||||
return (smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_StartFanControl) == 0) ? 0 : -EINVAL;
|
||||
}
|
||||
|
||||
|
||||
int iceland_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr)
|
||||
{
|
||||
return (smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_StopFanControl) == 0) ? 0 : -EINVAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 iceland_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 -EINVAL;
|
||||
|
||||
if (speed > 100) {
|
||||
pr_warning("Cannot set more than 100%% duty cycle. Set it to 100.\n");
|
||||
speed = 100;
|
||||
}
|
||||
|
||||
if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl))
|
||||
iceland_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 (0 == duty100)
|
||||
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 iceland_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 iceland_fan_ctrl_reset_fan_speed_to_default(struct pp_hwmgr *hwmgr)
|
||||
{
|
||||
int result;
|
||||
|
||||
if (hwmgr->thermal_controller.fanInfo.bNoFan)
|
||||
return 0;
|
||||
|
||||
if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl)) {
|
||||
result = iceland_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC);
|
||||
if (0 == result)
|
||||
result = iceland_fan_ctrl_start_smc_fan_control(hwmgr);
|
||||
} else
|
||||
result = iceland_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 iceland_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the remote temperature from the SIslands thermal controller.
|
||||
*
|
||||
* @param hwmgr The address of the hardware manager.
|
||||
*/
|
||||
int iceland_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 (0 != (0x200 & temp))
|
||||
temp = ICELAND_THERMAL_MAXIMUM_TEMP_READING;
|
||||
else
|
||||
temp = (temp & 0x1ff);
|
||||
|
||||
temp = 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 iceland_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, uint32_t low_temp, uint32_t high_temp)
|
||||
{
|
||||
uint32_t low = ICELAND_THERMAL_MINIMUM_ALERT_TEMP * PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
|
||||
uint32_t high = ICELAND_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 iceland_thermal_initialize(struct pp_hwmgr *hwmgr)
|
||||
{
|
||||
if (0 != 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 int iceland_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 &= ~(ICELAND_THERMAL_HIGH_ALERT_MASK | ICELAND_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 */
|
||||
return (smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_Thermal_Cntl_Enable) == 0) ? 0 : -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable thermal alerts on the RV770 thermal controller.
|
||||
* @param hwmgr The address of the hardware manager.
|
||||
*/
|
||||
static int iceland_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 |= (ICELAND_THERMAL_HIGH_ALERT_MASK | ICELAND_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->smumgr, PPSMC_MSG_Thermal_Cntl_Disable) == 0) ? 0 : -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Uninitialize the thermal controller.
|
||||
* Currently just disables alerts.
|
||||
* @param hwmgr The address of the hardware manager.
|
||||
*/
|
||||
int iceland_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr)
|
||||
{
|
||||
int result = iceland_thermal_disable_alert(hwmgr);
|
||||
|
||||
if (result)
|
||||
pr_warning("Failed to disable thermal alerts!\n");
|
||||
|
||||
if (hwmgr->thermal_controller.fanInfo.bNoFan)
|
||||
iceland_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
|
||||
*/
|
||||
int tf_iceland_thermal_setup_fan_table(struct pp_hwmgr *hwmgr, void *input, void *output, void *storage, int result)
|
||||
{
|
||||
struct iceland_hwmgr *data = (struct iceland_hwmgr *)(hwmgr->backend);
|
||||
SMU71_Discrete_FanTable fan_table = { FDO_MODE_HARDWARE };
|
||||
uint32_t duty100;
|
||||
uint32_t t_diff1, t_diff2, pwm_diff1, pwm_diff2;
|
||||
uint16_t fdo_min, slope1, slope2;
|
||||
uint32_t reference_clock;
|
||||
int res;
|
||||
uint64_t tmp64;
|
||||
|
||||
if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl))
|
||||
return 0;
|
||||
|
||||
if (0 == data->fan_table_start) {
|
||||
phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl);
|
||||
return 0;
|
||||
}
|
||||
|
||||
duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_FDO_CTRL1, FMAX_DUTY100);
|
||||
|
||||
if (0 == duty100) {
|
||||
phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl);
|
||||
return 0;
|
||||
}
|
||||
|
||||
tmp64 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin * duty100;
|
||||
do_div(tmp64, 10000);
|
||||
fdo_min = (uint16_t)tmp64;
|
||||
|
||||
t_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usTMed - hwmgr->thermal_controller.advanceFanControlParameters.usTMin;
|
||||
t_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usTHigh - hwmgr->thermal_controller.advanceFanControlParameters.usTMed;
|
||||
|
||||
pwm_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed - hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin;
|
||||
pwm_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh - hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed;
|
||||
|
||||
slope1 = (uint16_t)((50 + ((16 * duty100 * pwm_diff1) / t_diff1)) / 100);
|
||||
slope2 = (uint16_t)((50 + ((16 * duty100 * pwm_diff2) / t_diff2)) / 100);
|
||||
|
||||
fan_table.TempMin = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMin) / 100);
|
||||
fan_table.TempMed = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMed) / 100);
|
||||
fan_table.TempMax = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMax) / 100);
|
||||
|
||||
fan_table.Slope1 = cpu_to_be16(slope1);
|
||||
fan_table.Slope2 = cpu_to_be16(slope2);
|
||||
|
||||
fan_table.FdoMin = cpu_to_be16(fdo_min);
|
||||
|
||||
fan_table.HystDown = cpu_to_be16(hwmgr->thermal_controller.advanceFanControlParameters.ucTHyst);
|
||||
|
||||
fan_table.HystUp = cpu_to_be16(1);
|
||||
|
||||
fan_table.HystSlope = cpu_to_be16(1);
|
||||
|
||||
fan_table.TempRespLim = cpu_to_be16(5);
|
||||
|
||||
reference_clock = iceland_get_xclk(hwmgr);
|
||||
|
||||
fan_table.RefreshPeriod = cpu_to_be32((hwmgr->thermal_controller.advanceFanControlParameters.ulCycleDelay * reference_clock) / 1600);
|
||||
|
||||
fan_table.FdoMax = cpu_to_be16((uint16_t)duty100);
|
||||
|
||||
fan_table.TempSrc = (uint8_t)PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_MULT_THERMAL_CTRL, TEMP_SEL);
|
||||
|
||||
//fan_table.FanControl_GL_Flag = 1;
|
||||
|
||||
res = iceland_copy_bytes_to_smc(hwmgr->smumgr, data->fan_table_start, (uint8_t *)&fan_table, (uint32_t)sizeof(fan_table), data->sram_end);
|
||||
/* TO DO FOR SOME DEVICE ID 0X692b, send this msg return invalid command.
|
||||
if (res == 0 && hwmgr->thermal_controller.advanceFanControlParameters.ucMinimumPWMLimit != 0)
|
||||
res = (0 == smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, PPSMC_MSG_SetFanMinPwm, \
|
||||
hwmgr->thermal_controller.advanceFanControlParameters.ucMinimumPWMLimit) ? 0 : -1);
|
||||
|
||||
if (res == 0 && hwmgr->thermal_controller.advanceFanControlParameters.ulMinFanSCLKAcousticLimit != 0)
|
||||
res = (0 == smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, PPSMC_MSG_SetFanSclkTarget, \
|
||||
hwmgr->thermal_controller.advanceFanControlParameters.ulMinFanSCLKAcousticLimit) ? 0 : -1);
|
||||
|
||||
if (0 != res)
|
||||
phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl);
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
int tf_iceland_thermal_start_smc_fan_control(struct pp_hwmgr *hwmgr, void *input, void *output, void *storage, int result)
|
||||
{
|
||||
/* 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 (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl)) {
|
||||
iceland_fan_ctrl_start_smc_fan_control(hwmgr);
|
||||
iceland_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set temperature range for high and low alerts
|
||||
* @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 tf_iceland_thermal_set_temperature_range(struct pp_hwmgr *hwmgr,
|
||||
void *input, void *output, void *storage, int result)
|
||||
{
|
||||
struct PP_TemperatureRange *range = (struct PP_TemperatureRange *)input;
|
||||
|
||||
if (range == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
return iceland_thermal_set_temperature_range(hwmgr, range->min, range->max);
|
||||
}
|
||||
|
||||
/**
|
||||
* Programs one-time setting registers
|
||||
* @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 initialize thermal controller routine
|
||||
*/
|
||||
static int tf_iceland_thermal_initialize(struct pp_hwmgr *hwmgr, void *input,
|
||||
void *output, void *storage, int result)
|
||||
{
|
||||
return iceland_thermal_initialize(hwmgr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable high and low alerts
|
||||
* @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 enable alert routine
|
||||
*/
|
||||
static int tf_iceland_thermal_enable_alert(struct pp_hwmgr *hwmgr,
|
||||
void *input, void *output, void *storage, int result)
|
||||
{
|
||||
return iceland_thermal_enable_alert(hwmgr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable high and low alerts
|
||||
* @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 disable alert routine
|
||||
*/
|
||||
static int tf_iceland_thermal_disable_alert(struct pp_hwmgr *hwmgr, void *input, void *output, void *storage, int result)
|
||||
{
|
||||
return iceland_thermal_disable_alert(hwmgr);
|
||||
}
|
||||
|
||||
static const struct phm_master_table_item iceland_thermal_start_thermal_controller_master_list[] = {
|
||||
{ NULL, tf_iceland_thermal_initialize },
|
||||
{ NULL, tf_iceland_thermal_set_temperature_range },
|
||||
{ NULL, tf_iceland_thermal_enable_alert },
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
{ NULL, tf_iceland_thermal_setup_fan_table},
|
||||
{ NULL, tf_iceland_thermal_start_smc_fan_control},
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static const struct phm_master_table_header iceland_thermal_start_thermal_controller_master = {
|
||||
0,
|
||||
PHM_MasterTableFlag_None,
|
||||
iceland_thermal_start_thermal_controller_master_list
|
||||
};
|
||||
|
||||
static const struct phm_master_table_item iceland_thermal_set_temperature_range_master_list[] = {
|
||||
{ NULL, tf_iceland_thermal_disable_alert},
|
||||
{ NULL, tf_iceland_thermal_set_temperature_range},
|
||||
{ NULL, tf_iceland_thermal_enable_alert},
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static const struct phm_master_table_header iceland_thermal_set_temperature_range_master = {
|
||||
0,
|
||||
PHM_MasterTableFlag_None,
|
||||
iceland_thermal_set_temperature_range_master_list
|
||||
};
|
||||
|
||||
int iceland_thermal_ctrl_uninitialize_thermal_controller(struct pp_hwmgr *hwmgr)
|
||||
{
|
||||
if (!hwmgr->thermal_controller.fanInfo.bNoFan)
|
||||
iceland_fan_ctrl_set_default_mode(hwmgr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the thermal controller related functions in the Hardware Manager structure.
|
||||
* @param hwmgr The address of the hardware manager.
|
||||
* @exception Any error code from the low-level communication.
|
||||
*/
|
||||
int pp_iceland_thermal_initialize(struct pp_hwmgr *hwmgr)
|
||||
{
|
||||
int result;
|
||||
|
||||
result = phm_construct_table(hwmgr, &iceland_thermal_set_temperature_range_master, &(hwmgr->set_temperature_range));
|
||||
|
||||
if (0 == result) {
|
||||
result = phm_construct_table(hwmgr,
|
||||
&iceland_thermal_start_thermal_controller_master,
|
||||
&(hwmgr->start_thermal_controller));
|
||||
if (0 != result)
|
||||
phm_destroy_table(hwmgr, &(hwmgr->set_temperature_range));
|
||||
}
|
||||
|
||||
if (0 == result)
|
||||
hwmgr->fan_ctrl_is_in_default_mode = true;
|
||||
return result;
|
||||
}
|
||||
|
58
drivers/gpu/drm/amd/powerplay/hwmgr/iceland_thermal.h
Normal file
58
drivers/gpu/drm/amd/powerplay/hwmgr/iceland_thermal.h
Normal 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.
|
||||
*
|
||||
* Author: Huang Rui <ray.huang@amd.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ICELAND_THERMAL_H
|
||||
#define ICELAND_THERMAL_H
|
||||
|
||||
#include "hwmgr.h"
|
||||
|
||||
#define ICELAND_THERMAL_HIGH_ALERT_MASK 0x1
|
||||
#define ICELAND_THERMAL_LOW_ALERT_MASK 0x2
|
||||
|
||||
#define ICELAND_THERMAL_MINIMUM_TEMP_READING -256
|
||||
#define ICELAND_THERMAL_MAXIMUM_TEMP_READING 255
|
||||
|
||||
#define ICELAND_THERMAL_MINIMUM_ALERT_TEMP 0
|
||||
#define ICELAND_THERMAL_MAXIMUM_ALERT_TEMP 255
|
||||
|
||||
#define FDO_PWM_MODE_STATIC 1
|
||||
#define FDO_PWM_MODE_STATIC_RPM 5
|
||||
|
||||
|
||||
extern int iceland_thermal_get_temperature(struct pp_hwmgr *hwmgr);
|
||||
extern int iceland_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr);
|
||||
extern int iceland_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr, struct phm_fan_speed_info *fan_speed_info);
|
||||
extern int iceland_fan_ctrl_get_fan_speed_percent(struct pp_hwmgr *hwmgr, uint32_t *speed);
|
||||
extern int iceland_fan_ctrl_set_static_mode(struct pp_hwmgr *hwmgr, uint32_t mode);
|
||||
extern int iceland_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr, uint32_t speed);
|
||||
extern int iceland_fan_ctrl_reset_fan_speed_to_default(struct pp_hwmgr *hwmgr);
|
||||
extern int pp_iceland_thermal_initialize(struct pp_hwmgr *hwmgr);
|
||||
extern int iceland_thermal_ctrl_uninitialize_thermal_controller(struct pp_hwmgr *hwmgr);
|
||||
extern int iceland_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed);
|
||||
extern int iceland_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t *speed);
|
||||
extern int iceland_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr);
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user