#include "arcturus_ppsmc.h"
#include "nbio/nbio_7_4_offset.h"
#include "nbio/nbio_7_4_sh_mask.h"
+#include "thm/thm_11_0_2_offset.h"
+#include "thm/thm_11_0_2_sh_mask.h"
#include "amdgpu_xgmi.h"
#include <linux/i2c.h>
#include <linux/pci.h>
}
if (cap)
- *limit = smu_v11_0_get_max_power_limit(smu);
+ *limit = smu_get_max_power_limit(smu);
else
*limit = smu->power_limit;
log_buf);
}
+static int arcturus_set_thermal_range(struct smu_context *smu,
+ struct smu_temperature_range range)
+{
+ struct amdgpu_device *adev = smu->adev;
+ int low = SMU_THERMAL_MINIMUM_ALERT_TEMP;
+ int high = SMU_THERMAL_MAXIMUM_ALERT_TEMP;
+ uint32_t val;
+ struct smu_table_context *table_context = &smu->smu_table;
+ struct smu_11_0_powerplay_table *powerplay_table = table_context->power_play_table;
+
+ low = max(SMU_THERMAL_MINIMUM_ALERT_TEMP,
+ range.min / SMU_TEMPERATURE_UNITS_PER_CENTIGRADES);
+ high = min((uint16_t)SMU_THERMAL_MAXIMUM_ALERT_TEMP, powerplay_table->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, THERM_INTH_MASK, 0);
+ val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_INTL_MASK, 0);
+ val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, (high & 0xff));
+ val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, (low & 0xff));
+ val = val & (~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK);
+
+ WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL, val);
+
+ return 0;
+}
+
+static uint32_t atcturus_get_max_power_limit(struct smu_context *smu) {
+ uint32_t od_limit, max_power_limit;
+ struct smu_11_0_powerplay_table *powerplay_table = NULL;
+ struct smu_table_context *table_context = &smu->smu_table;
+ powerplay_table = table_context->power_play_table;
+
+ max_power_limit = smu_get_pptable_power_limit(smu);
+
+ if (!max_power_limit) {
+ // If we couldn't get the table limit, fall back on first-read value
+ if (!smu->default_power_limit)
+ smu->default_power_limit = smu->power_limit;
+ max_power_limit = smu->default_power_limit;
+ }
+
+ if (smu->od_enabled) {
+ od_limit = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_ODSETTING_POWERPERCENTAGE]);
+
+ pr_debug("ODSETTING_POWERPERCENTAGE: %d (default: %d)\n", od_limit, smu->default_power_limit);
+
+ max_power_limit *= (100 + od_limit);
+ max_power_limit /= 100;
+ }
+
+ return max_power_limit;
+}
+
static const struct pptable_funcs arcturus_ppt_funcs = {
/* translate smu index into arcturus specific index */
.get_smu_msg_index = arcturus_get_smu_msg_index,
.set_df_cstate = arcturus_set_df_cstate,
.allow_xgmi_power_down = arcturus_allow_xgmi_power_down,
.log_thermal_throttling_event = arcturus_log_thermal_throttling_event,
+ .set_thermal_range = arcturus_set_thermal_range,
+ .get_max_power_limit = atcturus_get_max_power_limit,
};
void arcturus_set_ppt_funcs(struct smu_context *smu)
int (*disable_umc_cdr_12gbps_workaround)(struct smu_context *smu);
int (*set_power_source)(struct smu_context *smu, enum smu_power_src_type power_src);
void (*log_thermal_throttling_event)(struct smu_context *smu);
+ int (*set_thermal_range)(struct smu_context *smu, struct smu_temperature_range range);
+ uint32_t (*get_max_power_limit)(struct smu_context *smu);
};
int smu_load_microcode(struct smu_context *smu);
int smu_v11_0_override_pcie_parameters(struct smu_context *smu);
-uint32_t smu_v11_0_get_max_power_limit(struct smu_context *smu);
-
int smu_v11_0_set_performance_level(struct smu_context *smu,
enum amd_dpm_forced_level level);
#include "smu_v11_0_ppsmc.h"
#include "nbio/nbio_2_3_offset.h"
#include "nbio/nbio_2_3_sh_mask.h"
+#include "thm/thm_11_0_2_offset.h"
+#include "thm/thm_11_0_2_sh_mask.h"
#include "asic_reg/mp/mp_11_0_sh_mask.h"
}
if (cap)
- *limit = smu_v11_0_get_max_power_limit(smu);
+ *limit = smu_get_max_power_limit(smu);
else
*limit = smu->power_limit;
return navi10_dummy_pstate_control(smu, true);
}
+static int navi10_set_thermal_range(struct smu_context *smu,
+ struct smu_temperature_range range)
+{
+ struct amdgpu_device *adev = smu->adev;
+ int low = SMU_THERMAL_MINIMUM_ALERT_TEMP;
+ int high = SMU_THERMAL_MAXIMUM_ALERT_TEMP;
+ uint32_t val;
+ struct smu_table_context *table_context = &smu->smu_table;
+ struct smu_11_0_powerplay_table *powerplay_table = table_context->power_play_table;
+
+ low = max(SMU_THERMAL_MINIMUM_ALERT_TEMP,
+ range.min / SMU_TEMPERATURE_UNITS_PER_CENTIGRADES);
+ high = min((uint16_t)SMU_THERMAL_MAXIMUM_ALERT_TEMP, powerplay_table->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, THERM_INTH_MASK, 0);
+ val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_INTL_MASK, 0);
+ val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, (high & 0xff));
+ val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, (low & 0xff));
+ val = val & (~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK);
+
+ WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL, val);
+
+ return 0;
+}
+
+static uint32_t navi10_get_max_power_limit(struct smu_context *smu) {
+ uint32_t od_limit, max_power_limit;
+ struct smu_11_0_powerplay_table *powerplay_table = NULL;
+ struct smu_table_context *table_context = &smu->smu_table;
+ powerplay_table = table_context->power_play_table;
+
+ max_power_limit = smu_get_pptable_power_limit(smu);
+
+ if (!max_power_limit) {
+ // If we couldn't get the table limit, fall back on first-read value
+ if (!smu->default_power_limit)
+ smu->default_power_limit = smu->power_limit;
+ max_power_limit = smu->default_power_limit;
+ }
+
+ if (smu->od_enabled) {
+ od_limit = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_ODSETTING_POWERPERCENTAGE]);
+
+ pr_debug("ODSETTING_POWERPERCENTAGE: %d (default: %d)\n", od_limit, smu->default_power_limit);
+
+ max_power_limit *= (100 + od_limit);
+ max_power_limit /= 100;
+ }
+
+ return max_power_limit;
+}
+
static const struct pptable_funcs navi10_ppt_funcs = {
.tables_init = navi10_tables_init,
.alloc_dpm_context = navi10_allocate_dpm_context,
.run_btc = navi10_run_btc,
.disable_umc_cdr_12gbps_workaround = navi10_disable_umc_cdr_12gbps_workaround,
.set_power_source = smu_v11_0_set_power_source,
+ .set_thermal_range = navi10_set_thermal_range,
+ .get_max_power_limit = navi10_get_max_power_limit,
};
void navi10_set_ppt_funcs(struct smu_context *smu)
#define smu_update_pcie_parameters(smu, pcie_gen_cap, pcie_width_cap) \
((smu)->ppt_funcs->update_pcie_parameters ? (smu)->ppt_funcs->update_pcie_parameters((smu), (pcie_gen_cap), (pcie_width_cap)) : 0)
+#define smu_set_thermal_range(smu, range) \
+ ((smu)->ppt_funcs->set_thermal_range ? (smu)->ppt_funcs->set_thermal_range((smu), (range)) : 0)
+#define smu_get_max_power_limit(smu) \
+ ((smu)->ppt_funcs->get_max_power_limit ? (smu)->ppt_funcs->get_max_power_limit((smu)) : 0)
+
#define smu_disable_umc_cdr_12gbps_workaround(smu) \
((smu)->ppt_funcs->disable_umc_cdr_12gbps_workaround ? (smu)->ppt_funcs->disable_umc_cdr_12gbps_workaround((smu)) : 0)
#include "atomfirmware.h"
#include "amdgpu_atomfirmware.h"
#include "smu_v11_0.h"
-#include "smu_v11_0_pptable.h"
#include "soc15_common.h"
#include "atom.h"
#include "amd_pcie.h"
return 0;
}
-uint32_t smu_v11_0_get_max_power_limit(struct smu_context *smu) {
- uint32_t od_limit, max_power_limit;
- struct smu_11_0_powerplay_table *powerplay_table = NULL;
- struct smu_table_context *table_context = &smu->smu_table;
- powerplay_table = table_context->power_play_table;
-
- max_power_limit = smu_get_pptable_power_limit(smu);
-
- if (!max_power_limit) {
- // If we couldn't get the table limit, fall back on first-read value
- if (!smu->default_power_limit)
- smu->default_power_limit = smu->power_limit;
- max_power_limit = smu->default_power_limit;
- }
-
- if (smu->od_enabled) {
- od_limit = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_ODSETTING_POWERPERCENTAGE]);
-
- pr_debug("ODSETTING_POWERPERCENTAGE: %d (default: %d)\n", od_limit, smu->default_power_limit);
-
- max_power_limit *= (100 + od_limit);
- max_power_limit /= 100;
- }
-
- return max_power_limit;
-}
-
int smu_v11_0_set_power_limit(struct smu_context *smu, uint32_t n)
{
int ret = 0;
uint32_t max_power_limit;
- max_power_limit = smu_v11_0_get_max_power_limit(smu);
+ max_power_limit = smu_get_max_power_limit(smu);
if (n > max_power_limit) {
pr_err("New power limit (%d) is over the max allowed %d\n",
return ret;
}
-static int smu_v11_0_set_thermal_range(struct smu_context *smu,
- struct smu_temperature_range range)
-{
- struct amdgpu_device *adev = smu->adev;
- int low = SMU_THERMAL_MINIMUM_ALERT_TEMP;
- int high = SMU_THERMAL_MAXIMUM_ALERT_TEMP;
- uint32_t val;
- struct smu_table_context *table_context = &smu->smu_table;
- struct smu_11_0_powerplay_table *powerplay_table = table_context->power_play_table;
-
- low = max(SMU_THERMAL_MINIMUM_ALERT_TEMP,
- range.min / SMU_TEMPERATURE_UNITS_PER_CENTIGRADES);
- high = min((uint16_t)SMU_THERMAL_MAXIMUM_ALERT_TEMP, powerplay_table->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 & 0xff));
- val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, (low & 0xff));
- val = val & (~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK);
-
- WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL, val);
-
- return 0;
-}
-
int smu_v11_0_enable_thermal_alert(struct smu_context *smu)
{
int ret = 0;
return ret;
if (smu->smu_table.thermal_controller_type) {
- ret = smu_v11_0_set_thermal_range(smu, range);
+ ret = smu_set_thermal_range(smu, range);
if (ret)
return ret;