aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/powerplay/smumgr
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/powerplay/smumgr')
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/Makefile5
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.c230
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.h2
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.c871
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.h98
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c258
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.h2
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/iceland_smumgr.c35
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/iceland_smumgr.h1
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c274
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.h1
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/rv_smumgr.c406
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/smu10_smumgr.c344
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/smu10_smumgr.h (renamed from drivers/gpu/drm/amd/powerplay/smumgr/rv_smumgr.h)26
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.c74
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.h12
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c891
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.h99
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c79
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.c199
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.h3
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.c426
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.h31
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/vega12_smumgr.c561
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/vega12_smumgr.h62
25 files changed, 2761 insertions, 2229 deletions
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/Makefile b/drivers/gpu/drm/amd/powerplay/smumgr/Makefile
index 98e701e4f553..958755075421 100644
--- a/drivers/gpu/drm/amd/powerplay/smumgr/Makefile
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/Makefile
@@ -23,9 +23,10 @@
# Makefile for the 'smu manager' sub-component of powerplay.
# It provides the smu management services for the driver.
-SMU_MGR = smumgr.o cz_smumgr.o tonga_smumgr.o fiji_smumgr.o \
+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 rv_smumgr.o ci_smumgr.o
+ smu7_smumgr.o vega10_smumgr.o smu10_smumgr.o ci_smumgr.o \
+ vega12_smumgr.o
AMD_PP_SMUMGR = $(addprefix $(AMD_PP_PATH)/smumgr/,$(SMU_MGR))
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.c
index 0b4a55660de4..08d000140eca 100644
--- a/drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.c
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.c
@@ -236,13 +236,10 @@ static int ci_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr,
static void ci_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr)
{
struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend);
- struct cgs_system_info sys_info = {0};
+ struct amdgpu_device *adev = hwmgr->adev;
uint32_t dev_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);
- dev_id = (uint32_t)sys_info.value;
+ dev_id = adev->pdev->device;
switch (dev_id) {
case 0x67BA:
@@ -411,8 +408,7 @@ static uint8_t ci_get_sleep_divider_id_from_clock(uint32_t clock,
}
static int ci_populate_single_graphic_level(struct pp_hwmgr *hwmgr,
- uint32_t clock, uint16_t sclk_al_threshold,
- struct SMU7_Discrete_GraphicsLevel *level)
+ uint32_t clock, struct SMU7_Discrete_GraphicsLevel *level)
{
int result;
struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
@@ -438,14 +434,14 @@ static int ci_populate_single_graphic_level(struct pp_hwmgr *hwmgr,
clock,
&level->MinVddcPhases);
- level->ActivityLevel = sclk_al_threshold;
+ level->ActivityLevel = data->current_profile_setting.sclk_activity;
level->CcPwrDynRm = 0;
level->CcPwrDynRm1 = 0;
level->EnabledForActivity = 0;
/* this level can be used for throttling.*/
level->EnabledForThrottle = 1;
- level->UpH = 0;
- level->DownH = 0;
+ level->UpH = data->current_profile_setting.sclk_up_hyst;
+ level->DownH = data->current_profile_setting.sclk_down_hyst;
level->VoltageDownH = 0;
level->PowerThrottle = 0;
@@ -492,7 +488,6 @@ static int ci_populate_all_graphic_levels(struct pp_hwmgr *hwmgr)
for (i = 0; i < dpm_table->sclk_table.count; i++) {
result = ci_populate_single_graphic_level(hwmgr,
dpm_table->sclk_table.dpm_levels[i].value,
- (uint16_t)smu_data->activity_target[i],
&levels[i]);
if (result)
return result;
@@ -860,10 +855,13 @@ static int ci_populate_smc_vddc_table(struct pp_hwmgr *hwmgr,
PP_ASSERT_WITH_CODE(0 == result, "do not populate SMC VDDC voltage table", return -EINVAL);
/* GPIO voltage control */
- if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->voltage_control)
- table->VddcLevel[count].Smio |= data->vddc_voltage_table.entries[count].smio_low;
- else
+ if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->voltage_control) {
+ table->VddcLevel[count].Smio = (uint8_t) count;
+ table->Smio[count] |= data->vddc_voltage_table.entries[count].smio_low;
+ table->SmioMaskVddcVid |= data->vddc_voltage_table.entries[count].smio_low;
+ } else {
table->VddcLevel[count].Smio = 0;
+ }
}
CONVERT_FROM_HOST_TO_SMC_UL(table->VddcLevelCount);
@@ -885,10 +883,13 @@ static int ci_populate_smc_vdd_ci_table(struct pp_hwmgr *hwmgr,
&(data->vddci_voltage_table.entries[count]),
&(table->VddciLevel[count]));
PP_ASSERT_WITH_CODE(result == 0, "do not populate SMC VDDCI voltage table", return -EINVAL);
- if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control)
- table->VddciLevel[count].Smio |= data->vddci_voltage_table.entries[count].smio_low;
- else
- table->VddciLevel[count].Smio |= 0;
+ if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) {
+ table->VddciLevel[count].Smio = (uint8_t) count;
+ table->Smio[count] |= data->vddci_voltage_table.entries[count].smio_low;
+ table->SmioMaskVddciVid |= data->vddci_voltage_table.entries[count].smio_low;
+ } else {
+ table->VddciLevel[count].Smio = 0;
+ }
}
CONVERT_FROM_HOST_TO_SMC_UL(table->VddciLevelCount);
@@ -910,10 +911,13 @@ static int ci_populate_smc_mvdd_table(struct pp_hwmgr *hwmgr,
&(data->mvdd_voltage_table.entries[count]),
&table->MvddLevel[count]);
PP_ASSERT_WITH_CODE(result == 0, "do not populate SMC mvdd voltage table", return -EINVAL);
- if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control)
- table->MvddLevel[count].Smio |= data->mvdd_voltage_table.entries[count].smio_low;
- else
- table->MvddLevel[count].Smio |= 0;
+ if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) {
+ table->MvddLevel[count].Smio = (uint8_t) count;
+ table->Smio[count] |= data->mvdd_voltage_table.entries[count].smio_low;
+ table->SmioMaskMvddVid |= data->mvdd_voltage_table.entries[count].smio_low;
+ } else {
+ table->MvddLevel[count].Smio = 0;
+ }
}
CONVERT_FROM_HOST_TO_SMC_UL(table->MvddLevelCount);
@@ -1217,12 +1221,12 @@ static int ci_populate_single_memory_level(
memory_level->EnabledForThrottle = 1;
memory_level->EnabledForActivity = 1;
- memory_level->UpH = 0;
- memory_level->DownH = 100;
+ memory_level->UpH = data->current_profile_setting.mclk_up_hyst;
+ memory_level->DownH = data->current_profile_setting.mclk_down_hyst;
memory_level->VoltageDownH = 0;
/* Indicates maximum activity level for this performance level.*/
- memory_level->ActivityLevel = (uint16_t)data->mclk_activity_target;
+ memory_level->ActivityLevel = data->current_profile_setting.mclk_activity;
memory_level->StutterEnable = 0;
memory_level->StrobeEnable = 0;
memory_level->EdcReadEnable = 0;
@@ -1302,7 +1306,7 @@ static int ci_populate_all_memory_levels(struct pp_hwmgr *hwmgr)
struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend);
struct smu7_dpm_table *dpm_table = &data->dpm_table;
int result;
- struct cgs_system_info sys_info = {0};
+ struct amdgpu_device *adev = hwmgr->adev;
uint32_t dev_id;
uint32_t level_array_address = smu_data->dpm_table_start + offsetof(SMU7_Discrete_DpmTable, MemoryLevel);
@@ -1323,10 +1327,7 @@ static int ci_populate_all_memory_levels(struct pp_hwmgr *hwmgr)
smu_data->smc_state_table.MemoryLevel[0].EnabledForActivity = 1;
- 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);
- dev_id = (uint32_t)sys_info.value;
+ dev_id = adev->pdev->device;
if ((dpm_table->mclk_table.count >= 2)
&& ((dev_id == 0x67B0) || (dev_id == 0x67B1))) {
@@ -1506,7 +1507,7 @@ static int ci_populate_smc_acpi_level(struct pp_hwmgr *hwmgr,
table->MemoryACPILevel.DownH = 100;
table->MemoryACPILevel.VoltageDownH = 0;
/* Indicates maximum activity level for this performance level.*/
- table->MemoryACPILevel.ActivityLevel = PP_HOST_TO_SMC_US((uint16_t)data->mclk_activity_target);
+ table->MemoryACPILevel.ActivityLevel = PP_HOST_TO_SMC_US(data->current_profile_setting.mclk_activity);
table->MemoryACPILevel.StutterEnable = 0;
table->MemoryACPILevel.StrobeEnable = 0;
@@ -1941,6 +1942,37 @@ static int ci_start_smc(struct pp_hwmgr *hwmgr)
return 0;
}
+static int ci_populate_vr_config(struct pp_hwmgr *hwmgr, SMU7_Discrete_DpmTable *table)
+{
+ struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
+ uint16_t config;
+
+ config = VR_SVI2_PLANE_1;
+ table->VRConfig |= (config<<VRCONF_VDDGFX_SHIFT);
+
+ if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) {
+ config = VR_SVI2_PLANE_2;
+ table->VRConfig |= config;
+ } else {
+ pr_info("VDDCshould be on SVI2 controller!");
+ }
+
+ if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) {
+ config = VR_SVI2_PLANE_2;
+ table->VRConfig |= (config<<VRCONF_VDDCI_SHIFT);
+ } else if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) {
+ config = VR_SMIO_PATTERN_1;
+ table->VRConfig |= (config<<VRCONF_VDDCI_SHIFT);
+ }
+
+ if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) {
+ config = VR_SMIO_PATTERN_2;
+ table->VRConfig |= (config<<VRCONF_MVDD_SHIFT);
+ }
+
+ return 0;
+}
+
static int ci_init_smc_table(struct pp_hwmgr *hwmgr)
{
int result;
@@ -2064,6 +2096,11 @@ static int ci_init_smc_table(struct pp_hwmgr *hwmgr)
table->PCIeBootLinkLevel = (uint8_t)data->dpm_table.pcie_speed_table.count;
table->PCIeGenInterval = 1;
+ result = ci_populate_vr_config(hwmgr, table);
+ PP_ASSERT_WITH_CODE(0 == result,
+ "Failed to populate VRConfig setting!", return result);
+ data->vr_config = table->VRConfig;
+
ci_populate_smc_svi2_config(hwmgr, table);
for (i = 0; i < SMU7_MAX_ENTRIES_SMIO; i++)
@@ -2084,6 +2121,7 @@ static int ci_init_smc_table(struct pp_hwmgr *hwmgr)
table->AcDcGpio = SMU7_UNUSED_GPIO_PIN;
CONVERT_FROM_HOST_TO_SMC_UL(table->SystemFlags);
+ CONVERT_FROM_HOST_TO_SMC_UL(table->VRConfig);
CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMaskVddcVid);
CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMaskVddcPhase);
CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMaskVddciVid);
@@ -2184,7 +2222,7 @@ static int ci_thermal_setup_fan_table(struct pp_hwmgr *hwmgr)
fan_table.TempRespLim = cpu_to_be16(5);
- reference_clock = smu7_get_xclk(hwmgr);
+ reference_clock = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev);
fan_table.RefreshPeriod = cpu_to_be32((hwmgr->thermal_controller.advanceFanControlParameters.ulCycleDelay * reference_clock) / 1600);
@@ -2728,35 +2766,8 @@ static bool ci_is_dpm_running(struct pp_hwmgr *hwmgr)
return ci_is_smc_ram_running(hwmgr);
}
-static int ci_populate_requested_graphic_levels(struct pp_hwmgr *hwmgr,
- struct amd_pp_profile *request)
-{
- struct ci_smumgr *smu_data = (struct ci_smumgr *)
- (hwmgr->smu_backend);
- struct SMU7_Discrete_GraphicsLevel *levels =
- smu_data->smc_state_table.GraphicsLevel;
- uint32_t array = smu_data->dpm_table_start +
- offsetof(SMU7_Discrete_DpmTable, GraphicsLevel);
- uint32_t array_size = sizeof(struct SMU7_Discrete_GraphicsLevel) *
- SMU7_MAX_LEVELS_GRAPHICS;
- uint32_t i;
-
- for (i = 0; i < smu_data->smc_state_table.GraphicsDpmLevelCount; i++) {
- levels[i].ActivityLevel =
- cpu_to_be16(request->activity_threshold);
- levels[i].EnabledForActivity = 1;
- levels[i].UpH = request->up_hyst;
- levels[i].DownH = request->down_hyst;
- }
-
- return ci_copy_bytes_to_smc(hwmgr, array, (uint8_t *)levels,
- array_size, SMC_RAM_END);
-}
-
-
static int ci_smu_init(struct pp_hwmgr *hwmgr)
{
- int i;
struct ci_smumgr *ci_priv = NULL;
ci_priv = kzalloc(sizeof(struct ci_smumgr), GFP_KERNEL);
@@ -2764,9 +2775,6 @@ static int ci_smu_init(struct pp_hwmgr *hwmgr)
if (ci_priv == NULL)
return -ENOMEM;
- for (i = 0; i < SMU7_MAX_LEVELS_GRAPHICS; i++)
- ci_priv->activity_target[i] = 30;
-
hwmgr->smu_backend = ci_priv;
return 0;
@@ -2785,6 +2793,102 @@ static int ci_start_smu(struct pp_hwmgr *hwmgr)
return 0;
}
+static int ci_update_dpm_settings(struct pp_hwmgr *hwmgr,
+ void *profile_setting)
+{
+ struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
+ struct ci_smumgr *smu_data = (struct ci_smumgr *)
+ (hwmgr->smu_backend);
+ struct profile_mode_setting *setting;
+ struct SMU7_Discrete_GraphicsLevel *levels =
+ smu_data->smc_state_table.GraphicsLevel;
+ uint32_t array = smu_data->dpm_table_start +
+ offsetof(SMU7_Discrete_DpmTable, GraphicsLevel);
+
+ uint32_t mclk_array = smu_data->dpm_table_start +
+ offsetof(SMU7_Discrete_DpmTable, MemoryLevel);
+ struct SMU7_Discrete_MemoryLevel *mclk_levels =
+ smu_data->smc_state_table.MemoryLevel;
+ uint32_t i;
+ uint32_t offset, up_hyst_offset, down_hyst_offset, clk_activity_offset, tmp;
+
+ if (profile_setting == NULL)
+ return -EINVAL;
+
+ setting = (struct profile_mode_setting *)profile_setting;
+
+ if (setting->bupdate_sclk) {
+ if (!data->sclk_dpm_key_disabled)
+ smum_send_msg_to_smc(hwmgr, PPSMC_MSG_SCLKDPM_FreezeLevel);
+ for (i = 0; i < smu_data->smc_state_table.GraphicsDpmLevelCount; i++) {
+ if (levels[i].ActivityLevel !=
+ cpu_to_be16(setting->sclk_activity)) {
+ levels[i].ActivityLevel = cpu_to_be16(setting->sclk_activity);
+
+ clk_activity_offset = array + (sizeof(SMU7_Discrete_GraphicsLevel) * i)
+ + offsetof(SMU7_Discrete_GraphicsLevel, ActivityLevel);
+ offset = clk_activity_offset & ~0x3;
+ tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset));
+ tmp = phm_set_field_to_u32(clk_activity_offset, tmp, levels[i].ActivityLevel, sizeof(uint16_t));
+ cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp));
+
+ }
+ if (levels[i].UpH != setting->sclk_up_hyst ||
+ levels[i].DownH != setting->sclk_down_hyst) {
+ levels[i].UpH = setting->sclk_up_hyst;
+ levels[i].DownH = setting->sclk_down_hyst;
+ up_hyst_offset = array + (sizeof(SMU7_Discrete_GraphicsLevel) * i)
+ + offsetof(SMU7_Discrete_GraphicsLevel, UpH);
+ down_hyst_offset = array + (sizeof(SMU7_Discrete_GraphicsLevel) * i)
+ + offsetof(SMU7_Discrete_GraphicsLevel, DownH);
+ offset = up_hyst_offset & ~0x3;
+ tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset));
+ tmp = phm_set_field_to_u32(up_hyst_offset, tmp, levels[i].UpH, sizeof(uint8_t));
+ tmp = phm_set_field_to_u32(down_hyst_offset, tmp, levels[i].DownH, sizeof(uint8_t));
+ cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp));
+ }
+ }
+ if (!data->sclk_dpm_key_disabled)
+ smum_send_msg_to_smc(hwmgr, PPSMC_MSG_SCLKDPM_UnfreezeLevel);
+ }
+
+ if (setting->bupdate_mclk) {
+ if (!data->mclk_dpm_key_disabled)
+ smum_send_msg_to_smc(hwmgr, PPSMC_MSG_MCLKDPM_FreezeLevel);
+ for (i = 0; i < smu_data->smc_state_table.MemoryDpmLevelCount; i++) {
+ if (mclk_levels[i].ActivityLevel !=
+ cpu_to_be16(setting->mclk_activity)) {
+ mclk_levels[i].ActivityLevel = cpu_to_be16(setting->mclk_activity);
+
+ clk_activity_offset = mclk_array + (sizeof(SMU7_Discrete_MemoryLevel) * i)
+ + offsetof(SMU7_Discrete_MemoryLevel, ActivityLevel);
+ offset = clk_activity_offset & ~0x3;
+ tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset));
+ tmp = phm_set_field_to_u32(clk_activity_offset, tmp, mclk_levels[i].ActivityLevel, sizeof(uint16_t));
+ cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp));
+
+ }
+ if (mclk_levels[i].UpH != setting->mclk_up_hyst ||
+ mclk_levels[i].DownH != setting->mclk_down_hyst) {
+ mclk_levels[i].UpH = setting->mclk_up_hyst;
+ mclk_levels[i].DownH = setting->mclk_down_hyst;
+ up_hyst_offset = mclk_array + (sizeof(SMU7_Discrete_MemoryLevel) * i)
+ + offsetof(SMU7_Discrete_MemoryLevel, UpH);
+ down_hyst_offset = mclk_array + (sizeof(SMU7_Discrete_MemoryLevel) * i)
+ + offsetof(SMU7_Discrete_MemoryLevel, DownH);
+ offset = up_hyst_offset & ~0x3;
+ tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset));
+ tmp = phm_set_field_to_u32(up_hyst_offset, tmp, mclk_levels[i].UpH, sizeof(uint8_t));
+ tmp = phm_set_field_to_u32(down_hyst_offset, tmp, mclk_levels[i].DownH, sizeof(uint8_t));
+ cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp));
+ }
+ }
+ if (!data->mclk_dpm_key_disabled)
+ smum_send_msg_to_smc(hwmgr, PPSMC_MSG_MCLKDPM_UnfreezeLevel);
+ }
+ return 0;
+}
+
const struct pp_smumgr_func ci_smu_funcs = {
.smu_init = ci_smu_init,
.smu_fini = ci_smu_fini,
@@ -2806,5 +2910,5 @@ const struct pp_smumgr_func ci_smu_funcs = {
.get_mac_definition = ci_get_mac_definition,
.initialize_mc_reg_table = ci_initialize_mc_reg_table,
.is_dpm_running = ci_is_dpm_running,
- .populate_requested_graphic_levels = ci_populate_requested_graphic_levels,
+ .update_dpm_settings = ci_update_dpm_settings,
};
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.h b/drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.h
index 8189cfa17c46..a8282705c569 100644
--- a/drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.h
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.h
@@ -70,8 +70,6 @@ struct ci_smumgr {
const struct ci_pt_defaults *power_tune_defaults;
SMU7_Discrete_MCRegisters mc_regs;
struct ci_mc_reg_table mc_reg_table;
- uint32_t activity_target[SMU7_MAX_LEVELS_GRAPHICS];
-
};
#endif
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.c
deleted file mode 100644
index 4d3aff381bca..000000000000
--- a/drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.c
+++ /dev/null
@@ -1,871 +0,0 @@
-/*
- * 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/delay.h>
-#include <linux/gfp.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/types.h>
-
-#include "cgs_common.h"
-#include "smu/smu_8_0_d.h"
-#include "smu/smu_8_0_sh_mask.h"
-#include "smu8.h"
-#include "smu8_fusion.h"
-#include "cz_smumgr.h"
-#include "cz_ppsmc.h"
-#include "smu_ucode_xfer_cz.h"
-#include "gca/gfx_8_0_d.h"
-#include "gca/gfx_8_0_sh_mask.h"
-#include "smumgr.h"
-
-#define SIZE_ALIGN_32(x) (((x) + 31) / 32 * 32)
-
-static const enum cz_scratch_entry firmware_list[] = {
- CZ_SCRATCH_ENTRY_UCODE_ID_SDMA0,
- CZ_SCRATCH_ENTRY_UCODE_ID_SDMA1,
- CZ_SCRATCH_ENTRY_UCODE_ID_CP_CE,
- CZ_SCRATCH_ENTRY_UCODE_ID_CP_PFP,
- CZ_SCRATCH_ENTRY_UCODE_ID_CP_ME,
- CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1,
- CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2,
- CZ_SCRATCH_ENTRY_UCODE_ID_RLC_G,
-};
-
-static int cz_smum_get_argument(struct pp_hwmgr *hwmgr)
-{
- if (hwmgr == NULL || hwmgr->device == NULL)
- return -EINVAL;
-
- return cgs_read_register(hwmgr->device,
- mmSMU_MP1_SRBM2P_ARG_0);
-}
-
-static int cz_send_msg_to_smc_async(struct pp_hwmgr *hwmgr, uint16_t msg)
-{
- int result = 0;
-
- if (hwmgr == NULL || hwmgr->device == NULL)
- return -EINVAL;
-
- result = PHM_WAIT_FIELD_UNEQUAL(hwmgr,
- SMU_MP1_SRBM2P_RESP_0, CONTENT, 0);
- if (result != 0) {
- pr_err("cz_send_msg_to_smc_async (0x%04x) failed\n", msg);
- return result;
- }
-
- cgs_write_register(hwmgr->device, mmSMU_MP1_SRBM2P_RESP_0, 0);
- cgs_write_register(hwmgr->device, mmSMU_MP1_SRBM2P_MSG_0, msg);
-
- return 0;
-}
-
-/* Send a message to the SMC, and wait for its response.*/
-static int cz_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg)
-{
- int result = 0;
-
- result = cz_send_msg_to_smc_async(hwmgr, msg);
- if (result != 0)
- return result;
-
- return PHM_WAIT_FIELD_UNEQUAL(hwmgr,
- SMU_MP1_SRBM2P_RESP_0, CONTENT, 0);
-}
-
-static int cz_set_smc_sram_address(struct pp_hwmgr *hwmgr,
- uint32_t smc_address, uint32_t limit)
-{
- if (hwmgr == NULL || hwmgr->device == NULL)
- return -EINVAL;
-
- if (0 != (3 & smc_address)) {
- pr_err("SMC address must be 4 byte aligned\n");
- return -EINVAL;
- }
-
- if (limit <= (smc_address + 3)) {
- pr_err("SMC address beyond the SMC RAM area\n");
- return -EINVAL;
- }
-
- cgs_write_register(hwmgr->device, mmMP0PUB_IND_INDEX_0,
- SMN_MP1_SRAM_START_ADDR + smc_address);
-
- return 0;
-}
-
-static int cz_write_smc_sram_dword(struct pp_hwmgr *hwmgr,
- uint32_t smc_address, uint32_t value, uint32_t limit)
-{
- int result;
-
- if (hwmgr == NULL || hwmgr->device == NULL)
- return -EINVAL;
-
- result = cz_set_smc_sram_address(hwmgr, smc_address, limit);
- if (!result)
- cgs_write_register(hwmgr->device, mmMP0PUB_IND_DATA_0, value);
-
- return result;
-}
-
-static int cz_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr,
- uint16_t msg, uint32_t parameter)
-{
- if (hwmgr == NULL || hwmgr->device == NULL)
- return -EINVAL;
-
- cgs_write_register(hwmgr->device, mmSMU_MP1_SRBM2P_ARG_0, parameter);
-
- return cz_send_msg_to_smc(hwmgr, msg);
-}
-
-static int cz_check_fw_load_finish(struct pp_hwmgr *hwmgr,
- uint32_t firmware)
-{
- int i;
- uint32_t index = SMN_MP1_SRAM_START_ADDR +
- SMU8_FIRMWARE_HEADER_LOCATION +
- offsetof(struct SMU8_Firmware_Header, UcodeLoadStatus);
-
- if (hwmgr == NULL || hwmgr->device == NULL)
- return -EINVAL;
-
- cgs_write_register(hwmgr->device, mmMP0PUB_IND_INDEX, index);
-
- for (i = 0; i < hwmgr->usec_timeout; i++) {
- if (firmware ==
- (cgs_read_register(hwmgr->device, mmMP0PUB_IND_DATA) & firmware))
- break;
- udelay(1);
- }
-
- if (i >= hwmgr->usec_timeout) {
- pr_err("SMU check loaded firmware failed.\n");
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int cz_load_mec_firmware(struct pp_hwmgr *hwmgr)
-{
- uint32_t reg_data;
- uint32_t tmp;
- int ret = 0;
- struct cgs_firmware_info info = {0};
- struct cz_smumgr *cz_smu;
-
- if (hwmgr == NULL || hwmgr->device == NULL)
- return -EINVAL;
-
- cz_smu = (struct cz_smumgr *)hwmgr->smu_backend;
- ret = cgs_get_firmware_info(hwmgr->device,
- CGS_UCODE_ID_CP_MEC, &info);
-
- if (ret)
- return -EINVAL;
-
- /* Disable MEC parsing/prefetching */
- tmp = cgs_read_register(hwmgr->device,
- mmCP_MEC_CNTL);
- tmp = PHM_SET_FIELD(tmp, CP_MEC_CNTL, MEC_ME1_HALT, 1);
- tmp = PHM_SET_FIELD(tmp, CP_MEC_CNTL, MEC_ME2_HALT, 1);
- cgs_write_register(hwmgr->device, mmCP_MEC_CNTL, tmp);
-
- tmp = cgs_read_register(hwmgr->device,
- mmCP_CPC_IC_BASE_CNTL);
-
- tmp = PHM_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, VMID, 0);
- tmp = PHM_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, ATC, 0);
- tmp = PHM_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, CACHE_POLICY, 0);
- tmp = PHM_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, MTYPE, 1);
- cgs_write_register(hwmgr->device, mmCP_CPC_IC_BASE_CNTL, tmp);
-
- reg_data = smu_lower_32_bits(info.mc_addr) &
- PHM_FIELD_MASK(CP_CPC_IC_BASE_LO, IC_BASE_LO);
- cgs_write_register(hwmgr->device, mmCP_CPC_IC_BASE_LO, reg_data);
-
- reg_data = smu_upper_32_bits(info.mc_addr) &
- PHM_FIELD_MASK(CP_CPC_IC_BASE_HI, IC_BASE_HI);
- cgs_write_register(hwmgr->device, mmCP_CPC_IC_BASE_HI, reg_data);
-
- return 0;
-}
-
-static uint8_t cz_translate_firmware_enum_to_arg(struct pp_hwmgr *hwmgr,
- enum cz_scratch_entry firmware_enum)
-{
- uint8_t ret = 0;
-
- switch (firmware_enum) {
- case CZ_SCRATCH_ENTRY_UCODE_ID_SDMA0:
- ret = UCODE_ID_SDMA0;
- break;
- case CZ_SCRATCH_ENTRY_UCODE_ID_SDMA1:
- if (hwmgr->chip_id == CHIP_STONEY)
- ret = UCODE_ID_SDMA0;
- else
- ret = UCODE_ID_SDMA1;
- break;
- case CZ_SCRATCH_ENTRY_UCODE_ID_CP_CE:
- ret = UCODE_ID_CP_CE;
- break;
- case CZ_SCRATCH_ENTRY_UCODE_ID_CP_PFP:
- ret = UCODE_ID_CP_PFP;
- break;
- case CZ_SCRATCH_ENTRY_UCODE_ID_CP_ME:
- ret = UCODE_ID_CP_ME;
- break;
- case CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1:
- ret = UCODE_ID_CP_MEC_JT1;
- break;
- case CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2:
- if (hwmgr->chip_id == CHIP_STONEY)
- ret = UCODE_ID_CP_MEC_JT1;
- else
- ret = UCODE_ID_CP_MEC_JT2;
- break;
- case CZ_SCRATCH_ENTRY_UCODE_ID_GMCON_RENG:
- ret = UCODE_ID_GMCON_RENG;
- break;
- case CZ_SCRATCH_ENTRY_UCODE_ID_RLC_G:
- ret = UCODE_ID_RLC_G;
- break;
- case CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH:
- ret = UCODE_ID_RLC_SCRATCH;
- break;
- case CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM:
- ret = UCODE_ID_RLC_SRM_ARAM;
- break;
- case CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM:
- ret = UCODE_ID_RLC_SRM_DRAM;
- break;
- case CZ_SCRATCH_ENTRY_UCODE_ID_DMCU_ERAM:
- ret = UCODE_ID_DMCU_ERAM;
- break;
- case CZ_SCRATCH_ENTRY_UCODE_ID_DMCU_IRAM:
- ret = UCODE_ID_DMCU_IRAM;
- break;
- case CZ_SCRATCH_ENTRY_UCODE_ID_POWER_PROFILING:
- ret = TASK_ARG_INIT_MM_PWR_LOG;
- break;
- case CZ_SCRATCH_ENTRY_DATA_ID_SDMA_HALT:
- case CZ_SCRATCH_ENTRY_DATA_ID_SYS_CLOCKGATING:
- case CZ_SCRATCH_ENTRY_DATA_ID_SDMA_RING_REGS:
- case CZ_SCRATCH_ENTRY_DATA_ID_NONGFX_REINIT:
- case CZ_SCRATCH_ENTRY_DATA_ID_SDMA_START:
- case CZ_SCRATCH_ENTRY_DATA_ID_IH_REGISTERS:
- ret = TASK_ARG_REG_MMIO;
- break;
- case CZ_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE:
- ret = TASK_ARG_INIT_CLK_TABLE;
- break;
- }
-
- return ret;
-}
-
-static enum cgs_ucode_id cz_convert_fw_type_to_cgs(uint32_t fw_type)
-{
- enum cgs_ucode_id result = CGS_UCODE_ID_MAXIMUM;
-
- switch (fw_type) {
- case UCODE_ID_SDMA0:
- result = CGS_UCODE_ID_SDMA0;
- break;
- case UCODE_ID_SDMA1:
- result = CGS_UCODE_ID_SDMA1;
- break;
- case UCODE_ID_CP_CE:
- result = CGS_UCODE_ID_CP_CE;
- break;
- case UCODE_ID_CP_PFP:
- result = CGS_UCODE_ID_CP_PFP;
- break;
- case UCODE_ID_CP_ME:
- result = CGS_UCODE_ID_CP_ME;
- break;
- case UCODE_ID_CP_MEC_JT1:
- result = CGS_UCODE_ID_CP_MEC_JT1;
- break;
- case UCODE_ID_CP_MEC_JT2:
- result = CGS_UCODE_ID_CP_MEC_JT2;
- break;
- case UCODE_ID_RLC_G:
- result = CGS_UCODE_ID_RLC_G;
- break;
- default:
- break;
- }
-
- return result;
-}
-
-static int cz_smu_populate_single_scratch_task(
- struct pp_hwmgr *hwmgr,
- enum cz_scratch_entry fw_enum,
- uint8_t type, bool is_last)
-{
- uint8_t i;
- struct cz_smumgr *cz_smu = (struct cz_smumgr *)hwmgr->smu_backend;
- struct TOC *toc = (struct TOC *)cz_smu->toc_buffer.kaddr;
- struct SMU_Task *task = &toc->tasks[cz_smu->toc_entry_used_count++];
-
- task->type = type;
- task->arg = cz_translate_firmware_enum_to_arg(hwmgr, fw_enum);
- task->next = is_last ? END_OF_TASK_LIST : cz_smu->toc_entry_used_count;
-
- for (i = 0; i < cz_smu->scratch_buffer_length; i++)
- if (cz_smu->scratch_buffer[i].firmware_ID == fw_enum)
- break;
-
- if (i >= cz_smu->scratch_buffer_length) {
- pr_err("Invalid Firmware Type\n");
- return -EINVAL;
- }
-
- task->addr.low = cz_smu->scratch_buffer[i].mc_addr_low;
- task->addr.high = cz_smu->scratch_buffer[i].mc_addr_high;
- task->size_bytes = cz_smu->scratch_buffer[i].data_size;
-
- if (CZ_SCRATCH_ENTRY_DATA_ID_IH_REGISTERS == fw_enum) {
- struct cz_ih_meta_data *pIHReg_restore =
- (struct cz_ih_meta_data *)cz_smu->scratch_buffer[i].kaddr;
- pIHReg_restore->command =
- METADATA_CMD_MODE0 | METADATA_PERFORM_ON_LOAD;
- }
-
- return 0;
-}
-
-static int cz_smu_populate_single_ucode_load_task(
- struct pp_hwmgr *hwmgr,
- enum cz_scratch_entry fw_enum,
- bool is_last)
-{
- uint8_t i;
- struct cz_smumgr *cz_smu = (struct cz_smumgr *)hwmgr->smu_backend;
- struct TOC *toc = (struct TOC *)cz_smu->toc_buffer.kaddr;
- struct SMU_Task *task = &toc->tasks[cz_smu->toc_entry_used_count++];
-
- task->type = TASK_TYPE_UCODE_LOAD;
- task->arg = cz_translate_firmware_enum_to_arg(hwmgr, fw_enum);
- task->next = is_last ? END_OF_TASK_LIST : cz_smu->toc_entry_used_count;
-
- for (i = 0; i < cz_smu->driver_buffer_length; i++)
- if (cz_smu->driver_buffer[i].firmware_ID == fw_enum)
- break;
-
- if (i >= cz_smu->driver_buffer_length) {
- pr_err("Invalid Firmware Type\n");
- return -EINVAL;
- }
-
- task->addr.low = cz_smu->driver_buffer[i].mc_addr_low;
- task->addr.high = cz_smu->driver_buffer[i].mc_addr_high;
- task->size_bytes = cz_smu->driver_buffer[i].data_size;
-
- return 0;
-}
-
-static int cz_smu_construct_toc_for_rlc_aram_save(struct pp_hwmgr *hwmgr)
-{
- struct cz_smumgr *cz_smu = (struct cz_smumgr *)hwmgr->smu_backend;
-
- cz_smu->toc_entry_aram = cz_smu->toc_entry_used_count;
- cz_smu_populate_single_scratch_task(hwmgr,
- CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM,
- TASK_TYPE_UCODE_SAVE, true);
-
- return 0;
-}
-
-static int cz_smu_initialize_toc_empty_job_list(struct pp_hwmgr *hwmgr)
-{
- int i;
- struct cz_smumgr *cz_smu = (struct cz_smumgr *)hwmgr->smu_backend;
- struct TOC *toc = (struct TOC *)cz_smu->toc_buffer.kaddr;
-
- for (i = 0; i < NUM_JOBLIST_ENTRIES; i++)
- toc->JobList[i] = (uint8_t)IGNORE_JOB;
-
- return 0;
-}
-
-static int cz_smu_construct_toc_for_vddgfx_enter(struct pp_hwmgr *hwmgr)
-{
- struct cz_smumgr *cz_smu = (struct cz_smumgr *)hwmgr->smu_backend;
- struct TOC *toc = (struct TOC *)cz_smu->toc_buffer.kaddr;
-
- toc->JobList[JOB_GFX_SAVE] = (uint8_t)cz_smu->toc_entry_used_count;
- cz_smu_populate_single_scratch_task(hwmgr,
- CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH,
- TASK_TYPE_UCODE_SAVE, false);
-
- cz_smu_populate_single_scratch_task(hwmgr,
- CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM,
- TASK_TYPE_UCODE_SAVE, true);
-
- return 0;
-}
-
-
-static int cz_smu_construct_toc_for_vddgfx_exit(struct pp_hwmgr *hwmgr)
-{
- struct cz_smumgr *cz_smu = (struct cz_smumgr *)hwmgr->smu_backend;
- struct TOC *toc = (struct TOC *)cz_smu->toc_buffer.kaddr;
-
- toc->JobList[JOB_GFX_RESTORE] = (uint8_t)cz_smu->toc_entry_used_count;
-
- cz_smu_populate_single_ucode_load_task(hwmgr,
- CZ_SCRATCH_ENTRY_UCODE_ID_CP_CE, false);
- cz_smu_populate_single_ucode_load_task(hwmgr,
- CZ_SCRATCH_ENTRY_UCODE_ID_CP_PFP, false);
- cz_smu_populate_single_ucode_load_task(hwmgr,
- CZ_SCRATCH_ENTRY_UCODE_ID_CP_ME, false);
- cz_smu_populate_single_ucode_load_task(hwmgr,
- CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, false);
-
- if (hwmgr->chip_id == CHIP_STONEY)
- cz_smu_populate_single_ucode_load_task(hwmgr,
- CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, false);
- else
- cz_smu_populate_single_ucode_load_task(hwmgr,
- CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2, false);
-
- cz_smu_populate_single_ucode_load_task(hwmgr,
- CZ_SCRATCH_ENTRY_UCODE_ID_RLC_G, false);
-
- /* populate scratch */
- cz_smu_populate_single_scratch_task(hwmgr,
- CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH,
- TASK_TYPE_UCODE_LOAD, false);
-
- cz_smu_populate_single_scratch_task(hwmgr,
- CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM,
- TASK_TYPE_UCODE_LOAD, false);
-
- cz_smu_populate_single_scratch_task(hwmgr,
- CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM,
- TASK_TYPE_UCODE_LOAD, true);
-
- return 0;
-}
-
-static int cz_smu_construct_toc_for_power_profiling(struct pp_hwmgr *hwmgr)
-{
- struct cz_smumgr *cz_smu = (struct cz_smumgr *)hwmgr->smu_backend;
-
- cz_smu->toc_entry_power_profiling_index = cz_smu->toc_entry_used_count;
-
- cz_smu_populate_single_scratch_task(hwmgr,
- CZ_SCRATCH_ENTRY_UCODE_ID_POWER_PROFILING,
- TASK_TYPE_INITIALIZE, true);
- return 0;
-}
-
-static int cz_smu_construct_toc_for_bootup(struct pp_hwmgr *hwmgr)
-{
- struct cz_smumgr *cz_smu = (struct cz_smumgr *)hwmgr->smu_backend;
-
- cz_smu->toc_entry_initialize_index = cz_smu->toc_entry_used_count;
-
- cz_smu_populate_single_ucode_load_task(hwmgr,
- CZ_SCRATCH_ENTRY_UCODE_ID_SDMA0, false);
- if (hwmgr->chip_id != CHIP_STONEY)
- cz_smu_populate_single_ucode_load_task(hwmgr,
- CZ_SCRATCH_ENTRY_UCODE_ID_SDMA1, false);
- cz_smu_populate_single_ucode_load_task(hwmgr,
- CZ_SCRATCH_ENTRY_UCODE_ID_CP_CE, false);
- cz_smu_populate_single_ucode_load_task(hwmgr,
- CZ_SCRATCH_ENTRY_UCODE_ID_CP_PFP, false);
- cz_smu_populate_single_ucode_load_task(hwmgr,
- CZ_SCRATCH_ENTRY_UCODE_ID_CP_ME, false);
- cz_smu_populate_single_ucode_load_task(hwmgr,
- CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, false);
- if (hwmgr->chip_id != CHIP_STONEY)
- cz_smu_populate_single_ucode_load_task(hwmgr,
- CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2, false);
- cz_smu_populate_single_ucode_load_task(hwmgr,
- CZ_SCRATCH_ENTRY_UCODE_ID_RLC_G, true);
-
- return 0;
-}
-
-static int cz_smu_construct_toc_for_clock_table(struct pp_hwmgr *hwmgr)
-{
- struct cz_smumgr *cz_smu = (struct cz_smumgr *)hwmgr->smu_backend;
-
- cz_smu->toc_entry_clock_table = cz_smu->toc_entry_used_count;
-
- cz_smu_populate_single_scratch_task(hwmgr,
- CZ_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE,
- TASK_TYPE_INITIALIZE, true);
-
- return 0;
-}
-
-static int cz_smu_construct_toc(struct pp_hwmgr *hwmgr)
-{
- struct cz_smumgr *cz_smu = (struct cz_smumgr *)hwmgr->smu_backend;
-
- cz_smu->toc_entry_used_count = 0;
- cz_smu_initialize_toc_empty_job_list(hwmgr);
- cz_smu_construct_toc_for_rlc_aram_save(hwmgr);
- cz_smu_construct_toc_for_vddgfx_enter(hwmgr);
- cz_smu_construct_toc_for_vddgfx_exit(hwmgr);
- cz_smu_construct_toc_for_power_profiling(hwmgr);
- cz_smu_construct_toc_for_bootup(hwmgr);
- cz_smu_construct_toc_for_clock_table(hwmgr);
-
- return 0;
-}
-
-static int cz_smu_populate_firmware_entries(struct pp_hwmgr *hwmgr)
-{
- struct cz_smumgr *cz_smu = (struct cz_smumgr *)hwmgr->smu_backend;
- uint32_t firmware_type;
- uint32_t i;
- int ret;
- enum cgs_ucode_id ucode_id;
- struct cgs_firmware_info info = {0};
-
- cz_smu->driver_buffer_length = 0;
-
- for (i = 0; i < ARRAY_SIZE(firmware_list); i++) {
-
- firmware_type = cz_translate_firmware_enum_to_arg(hwmgr,
- firmware_list[i]);
-
- ucode_id = cz_convert_fw_type_to_cgs(firmware_type);
-
- ret = cgs_get_firmware_info(hwmgr->device,
- ucode_id, &info);
-
- if (ret == 0) {
- cz_smu->driver_buffer[i].mc_addr_high =
- smu_upper_32_bits(info.mc_addr);
-
- cz_smu->driver_buffer[i].mc_addr_low =
- smu_lower_32_bits(info.mc_addr);
-
- cz_smu->driver_buffer[i].data_size = info.image_size;
-
- cz_smu->driver_buffer[i].firmware_ID = firmware_list[i];
- cz_smu->driver_buffer_length++;
- }
- }
-
- return 0;
-}
-
-static int cz_smu_populate_single_scratch_entry(
- struct pp_hwmgr *hwmgr,
- enum cz_scratch_entry scratch_type,
- uint32_t ulsize_byte,
- struct cz_buffer_entry *entry)
-{
- struct cz_smumgr *cz_smu = (struct cz_smumgr *)hwmgr->smu_backend;
- long long mc_addr =
- ((long long)(cz_smu->smu_buffer.mc_addr_high) << 32)
- | cz_smu->smu_buffer.mc_addr_low;
-
- uint32_t ulsize_aligned = SIZE_ALIGN_32(ulsize_byte);
-
- mc_addr += cz_smu->smu_buffer_used_bytes;
-
- entry->data_size = ulsize_byte;
- entry->kaddr = (char *) cz_smu->smu_buffer.kaddr +
- cz_smu->smu_buffer_used_bytes;
- entry->mc_addr_low = smu_lower_32_bits(mc_addr);
- entry->mc_addr_high = smu_upper_32_bits(mc_addr);
- entry->firmware_ID = scratch_type;
-
- cz_smu->smu_buffer_used_bytes += ulsize_aligned;
-
- return 0;
-}
-
-static int cz_download_pptable_settings(struct pp_hwmgr *hwmgr, void **table)
-{
- struct cz_smumgr *cz_smu = (struct cz_smumgr *)hwmgr->smu_backend;
- unsigned long i;
-
- for (i = 0; i < cz_smu->scratch_buffer_length; i++) {
- if (cz_smu->scratch_buffer[i].firmware_ID
- == CZ_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE)
- break;
- }
-
- *table = (struct SMU8_Fusion_ClkTable *)cz_smu->scratch_buffer[i].kaddr;
-
- cz_send_msg_to_smc_with_parameter(hwmgr,
- PPSMC_MSG_SetClkTableAddrHi,
- cz_smu->scratch_buffer[i].mc_addr_high);
-
- cz_send_msg_to_smc_with_parameter(hwmgr,
- PPSMC_MSG_SetClkTableAddrLo,
- cz_smu->scratch_buffer[i].mc_addr_low);
-
- cz_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_ExecuteJob,
- cz_smu->toc_entry_clock_table);
-
- cz_send_msg_to_smc(hwmgr, PPSMC_MSG_ClkTableXferToDram);
-
- return 0;
-}
-
-static int cz_upload_pptable_settings(struct pp_hwmgr *hwmgr)
-{
- struct cz_smumgr *cz_smu = (struct cz_smumgr *)hwmgr->smu_backend;
- unsigned long i;
-
- for (i = 0; i < cz_smu->scratch_buffer_length; i++) {
- if (cz_smu->scratch_buffer[i].firmware_ID
- == CZ_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE)
- break;
- }
-
- cz_send_msg_to_smc_with_parameter(hwmgr,
- PPSMC_MSG_SetClkTableAddrHi,
- cz_smu->scratch_buffer[i].mc_addr_high);
-
- cz_send_msg_to_smc_with_parameter(hwmgr,
- PPSMC_MSG_SetClkTableAddrLo,
- cz_smu->scratch_buffer[i].mc_addr_low);
-
- cz_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_ExecuteJob,
- cz_smu->toc_entry_clock_table);
-
- cz_send_msg_to_smc(hwmgr, PPSMC_MSG_ClkTableXferToSmu);
-
- return 0;
-}
-
-static int cz_request_smu_load_fw(struct pp_hwmgr *hwmgr)
-{
- struct cz_smumgr *cz_smu = (struct cz_smumgr *)(hwmgr->smu_backend);
- uint32_t smc_address;
-
- if (!hwmgr->reload_fw) {
- pr_info("skip reloading...\n");
- return 0;
- }
-
- cz_smu_populate_firmware_entries(hwmgr);
-
- cz_smu_construct_toc(hwmgr);
-
- smc_address = SMU8_FIRMWARE_HEADER_LOCATION +
- offsetof(struct SMU8_Firmware_Header, UcodeLoadStatus);
-
- cz_write_smc_sram_dword(hwmgr, smc_address, 0, smc_address+4);
-
- cz_send_msg_to_smc_with_parameter(hwmgr,
- PPSMC_MSG_DriverDramAddrHi,
- cz_smu->toc_buffer.mc_addr_high);
-
- cz_send_msg_to_smc_with_parameter(hwmgr,
- PPSMC_MSG_DriverDramAddrLo,
- cz_smu->toc_buffer.mc_addr_low);
-
- cz_send_msg_to_smc(hwmgr, PPSMC_MSG_InitJobs);
-
- cz_send_msg_to_smc_with_parameter(hwmgr,
- PPSMC_MSG_ExecuteJob,
- cz_smu->toc_entry_aram);
- cz_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_ExecuteJob,
- cz_smu->toc_entry_power_profiling_index);
-
- return cz_send_msg_to_smc_with_parameter(hwmgr,
- PPSMC_MSG_ExecuteJob,
- cz_smu->toc_entry_initialize_index);
-}
-
-static int cz_start_smu(struct pp_hwmgr *hwmgr)
-{
- int ret = 0;
- uint32_t fw_to_check = 0;
- struct cgs_firmware_info info = {0};
- uint32_t index = SMN_MP1_SRAM_START_ADDR +
- SMU8_FIRMWARE_HEADER_LOCATION +
- offsetof(struct SMU8_Firmware_Header, Version);
-
-
- if (hwmgr == NULL || hwmgr->device == NULL)
- return -EINVAL;
-
- cgs_write_register(hwmgr->device, mmMP0PUB_IND_INDEX, index);
- hwmgr->smu_version = cgs_read_register(hwmgr->device, mmMP0PUB_IND_DATA);
- info.version = hwmgr->smu_version >> 8;
- cgs_get_firmware_info(hwmgr->device, CGS_UCODE_ID_SMU, &info);
-
- fw_to_check = UCODE_ID_RLC_G_MASK |
- UCODE_ID_SDMA0_MASK |
- UCODE_ID_SDMA1_MASK |
- UCODE_ID_CP_CE_MASK |
- UCODE_ID_CP_ME_MASK |
- UCODE_ID_CP_PFP_MASK |
- UCODE_ID_CP_MEC_JT1_MASK |
- UCODE_ID_CP_MEC_JT2_MASK;
-
- if (hwmgr->chip_id == CHIP_STONEY)
- fw_to_check &= ~(UCODE_ID_SDMA1_MASK | UCODE_ID_CP_MEC_JT2_MASK);
-
- ret = cz_request_smu_load_fw(hwmgr);
- if (ret)
- pr_err("SMU firmware load failed\n");
-
- cz_check_fw_load_finish(hwmgr, fw_to_check);
-
- ret = cz_load_mec_firmware(hwmgr);
- if (ret)
- pr_err("Mec Firmware load failed\n");
-
- return ret;
-}
-
-static int cz_smu_init(struct pp_hwmgr *hwmgr)
-{
- uint64_t mc_addr = 0;
- int ret = 0;
- struct cz_smumgr *cz_smu;
-
- cz_smu = kzalloc(sizeof(struct cz_smumgr), GFP_KERNEL);
- if (cz_smu == NULL)
- return -ENOMEM;
-
- hwmgr->smu_backend = cz_smu;
-
- cz_smu->toc_buffer.data_size = 4096;
- cz_smu->smu_buffer.data_size =
- ALIGN(UCODE_ID_RLC_SCRATCH_SIZE_BYTE, 32) +
- ALIGN(UCODE_ID_RLC_SRM_ARAM_SIZE_BYTE, 32) +
- ALIGN(UCODE_ID_RLC_SRM_DRAM_SIZE_BYTE, 32) +
- ALIGN(sizeof(struct SMU8_MultimediaPowerLogData), 32) +
- ALIGN(sizeof(struct SMU8_Fusion_ClkTable), 32);
-
- ret = smu_allocate_memory(hwmgr->device,
- cz_smu->toc_buffer.data_size,
- CGS_GPU_MEM_TYPE__GART_CACHEABLE,
- PAGE_SIZE,
- &mc_addr,
- &cz_smu->toc_buffer.kaddr,
- &cz_smu->toc_buffer.handle);
- if (ret != 0)
- return -1;
-
- cz_smu->toc_buffer.mc_addr_high = smu_upper_32_bits(mc_addr);
- cz_smu->toc_buffer.mc_addr_low = smu_lower_32_bits(mc_addr);
-
- ret = smu_allocate_memory(hwmgr->device,
- cz_smu->smu_buffer.data_size,
- CGS_GPU_MEM_TYPE__GART_CACHEABLE,
- PAGE_SIZE,
- &mc_addr,
- &cz_smu->smu_buffer.kaddr,
- &cz_smu->smu_buffer.handle);
- if (ret != 0)
- return -1;
-
- cz_smu->smu_buffer.mc_addr_high = smu_upper_32_bits(mc_addr);
- cz_smu->smu_buffer.mc_addr_low = smu_lower_32_bits(mc_addr);
-
- if (0 != cz_smu_populate_single_scratch_entry(hwmgr,
- CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH,
- UCODE_ID_RLC_SCRATCH_SIZE_BYTE,
- &cz_smu->scratch_buffer[cz_smu->scratch_buffer_length++])) {
- pr_err("Error when Populate Firmware Entry.\n");
- return -1;
- }
-
- if (0 != cz_smu_populate_single_scratch_entry(hwmgr,
- CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM,
- UCODE_ID_RLC_SRM_ARAM_SIZE_BYTE,
- &cz_smu->scratch_buffer[cz_smu->scratch_buffer_length++])) {
- pr_err("Error when Populate Firmware Entry.\n");
- return -1;
- }
- if (0 != cz_smu_populate_single_scratch_entry(hwmgr,
- CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM,
- UCODE_ID_RLC_SRM_DRAM_SIZE_BYTE,
- &cz_smu->scratch_buffer[cz_smu->scratch_buffer_length++])) {
- pr_err("Error when Populate Firmware Entry.\n");
- return -1;
- }
-
- if (0 != cz_smu_populate_single_scratch_entry(hwmgr,
- CZ_SCRATCH_ENTRY_UCODE_ID_POWER_PROFILING,
- sizeof(struct SMU8_MultimediaPowerLogData),
- &cz_smu->scratch_buffer[cz_smu->scratch_buffer_length++])) {
- pr_err("Error when Populate Firmware Entry.\n");
- return -1;
- }
-
- if (0 != cz_smu_populate_single_scratch_entry(hwmgr,
- CZ_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE,
- sizeof(struct SMU8_Fusion_ClkTable),
- &cz_smu->scratch_buffer[cz_smu->scratch_buffer_length++])) {
- pr_err("Error when Populate Firmware Entry.\n");
- return -1;
- }
-
- return 0;
-}
-
-static int cz_smu_fini(struct pp_hwmgr *hwmgr)
-{
- struct cz_smumgr *cz_smu;
-
- if (hwmgr == NULL || hwmgr->device == NULL)
- return -EINVAL;
-
- cz_smu = (struct cz_smumgr *)hwmgr->smu_backend;
- if (cz_smu) {
- cgs_free_gpu_mem(hwmgr->device,
- cz_smu->toc_buffer.handle);
- cgs_free_gpu_mem(hwmgr->device,
- cz_smu->smu_buffer.handle);
- kfree(cz_smu);
- }
-
- return 0;
-}
-
-const struct pp_smumgr_func cz_smu_funcs = {
- .smu_init = cz_smu_init,
- .smu_fini = cz_smu_fini,
- .start_smu = cz_start_smu,
- .check_fw_load_finish = cz_check_fw_load_finish,
- .request_smu_load_fw = NULL,
- .request_smu_load_specific_fw = NULL,
- .get_argument = cz_smum_get_argument,
- .send_msg_to_smc = cz_send_msg_to_smc,
- .send_msg_to_smc_with_parameter = cz_send_msg_to_smc_with_parameter,
- .download_pptable_settings = cz_download_pptable_settings,
- .upload_pptable_settings = cz_upload_pptable_settings,
-};
-
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.h b/drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.h
deleted file mode 100644
index 7c3a290c8957..000000000000
--- a/drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * 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 _CZ_SMUMGR_H_
-#define _CZ_SMUMGR_H_
-
-
-#define MAX_NUM_FIRMWARE 8
-#define MAX_NUM_SCRATCH 11
-#define CZ_SCRATCH_SIZE_NONGFX_CLOCKGATING 1024
-#define CZ_SCRATCH_SIZE_NONGFX_GOLDENSETTING 2048
-#define CZ_SCRATCH_SIZE_SDMA_METADATA 1024
-#define CZ_SCRATCH_SIZE_IH ((2*256+1)*4)
-
-enum cz_scratch_entry {
- CZ_SCRATCH_ENTRY_UCODE_ID_SDMA0 = 0,
- CZ_SCRATCH_ENTRY_UCODE_ID_SDMA1,
- CZ_SCRATCH_ENTRY_UCODE_ID_CP_CE,
- CZ_SCRATCH_ENTRY_UCODE_ID_CP_PFP,
- CZ_SCRATCH_ENTRY_UCODE_ID_CP_ME,
- CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1,
- CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2,
- CZ_SCRATCH_ENTRY_UCODE_ID_GMCON_RENG,
- CZ_SCRATCH_ENTRY_UCODE_ID_RLC_G,
- CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH,
- CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM,
- CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM,
- CZ_SCRATCH_ENTRY_UCODE_ID_DMCU_ERAM,
- CZ_SCRATCH_ENTRY_UCODE_ID_DMCU_IRAM,
- CZ_SCRATCH_ENTRY_UCODE_ID_POWER_PROFILING,
- CZ_SCRATCH_ENTRY_DATA_ID_SDMA_HALT,
- CZ_SCRATCH_ENTRY_DATA_ID_SYS_CLOCKGATING,
- CZ_SCRATCH_ENTRY_DATA_ID_SDMA_RING_REGS,
- CZ_SCRATCH_ENTRY_DATA_ID_NONGFX_REINIT,
- CZ_SCRATCH_ENTRY_DATA_ID_SDMA_START,
- CZ_SCRATCH_ENTRY_DATA_ID_IH_REGISTERS,
- CZ_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE
-};
-
-struct cz_buffer_entry {
- uint32_t data_size;
- uint32_t mc_addr_low;
- uint32_t mc_addr_high;
- void *kaddr;
- enum cz_scratch_entry firmware_ID;
- unsigned long handle; /* as bo handle used when release bo */
-};
-
-struct cz_register_index_data_pair {
- uint32_t offset;
- uint32_t value;
-};
-
-struct cz_ih_meta_data {
- uint32_t command;
- struct cz_register_index_data_pair register_index_value_pair[1];
-};
-
-struct cz_smumgr {
- uint8_t driver_buffer_length;
- uint8_t scratch_buffer_length;
- uint16_t toc_entry_used_count;
- uint16_t toc_entry_initialize_index;
- uint16_t toc_entry_power_profiling_index;
- uint16_t toc_entry_aram;
- uint16_t toc_entry_ih_register_restore_task_index;
- uint16_t toc_entry_clock_table;
- uint16_t ih_register_restore_task_size;
- uint16_t smu_buffer_used_bytes;
-
- struct cz_buffer_entry toc_buffer;
- struct cz_buffer_entry smu_buffer;
- struct cz_buffer_entry firmware_buffer;
- struct cz_buffer_entry driver_buffer[MAX_NUM_FIRMWARE];
- struct cz_buffer_entry meta_data_buffer[MAX_NUM_FIRMWARE];
- struct cz_buffer_entry scratch_buffer[MAX_NUM_SCRATCH];
-};
-
-#endif
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c
index 085d81c8b332..faef78321446 100644
--- a/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c
@@ -205,9 +205,9 @@ static int fiji_start_avfs_btc(struct pp_hwmgr *hwmgr)
int result = 0;
struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend);
- if (0 != smu_data->avfs.avfs_btc_param) {
+ if (0 != smu_data->avfs_btc_param) {
if (0 != smu7_send_msg_to_smc_with_parameter(hwmgr,
- PPSMC_MSG_PerformBtc, smu_data->avfs.avfs_btc_param)) {
+ PPSMC_MSG_PerformBtc, smu_data->avfs_btc_param)) {
pr_info("[AVFS][Fiji_PerformBtc] PerformBTC SMU msg failed");
result = -EINVAL;
}
@@ -261,43 +261,24 @@ static int fiji_setup_graphics_level_structure(struct pp_hwmgr *hwmgr)
return 0;
}
-static int fiji_avfs_event_mgr(struct pp_hwmgr *hwmgr, bool smu_started)
+static int fiji_avfs_event_mgr(struct pp_hwmgr *hwmgr)
{
- struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend);
+ if (!hwmgr->avfs_supported)
+ return 0;
- switch (smu_data->avfs.avfs_btc_status) {
- case AVFS_BTC_COMPLETED_PREVIOUSLY:
- break;
+ PP_ASSERT_WITH_CODE(0 == fiji_setup_graphics_level_structure(hwmgr),
+ "[AVFS][fiji_avfs_event_mgr] Could not Copy Graphics Level"
+ " table over to SMU",
+ return -EINVAL);
+ PP_ASSERT_WITH_CODE(0 == smu7_setup_pwr_virus(hwmgr),
+ "[AVFS][fiji_avfs_event_mgr] Could not setup "
+ "Pwr Virus for AVFS ",
+ return -EINVAL);
+ PP_ASSERT_WITH_CODE(0 == fiji_start_avfs_btc(hwmgr),
+ "[AVFS][fiji_avfs_event_mgr] Failure at "
+ "fiji_start_avfs_btc. AVFS Disabled",
+ return -EINVAL);
- case AVFS_BTC_BOOT: /*Cold Boot State - Post SMU Start*/
- if (!smu_started)
- break;
- smu_data->avfs.avfs_btc_status = AVFS_BTC_FAILED;
- PP_ASSERT_WITH_CODE(0 == fiji_setup_graphics_level_structure(hwmgr),
- "[AVFS][fiji_avfs_event_mgr] Could not Copy Graphics Level"
- " table over to SMU",
- return -EINVAL;);
- smu_data->avfs.avfs_btc_status = AVFS_BTC_VIRUS_FAIL;
- PP_ASSERT_WITH_CODE(0 == smu7_setup_pwr_virus(hwmgr),
- "[AVFS][fiji_avfs_event_mgr] Could not setup "
- "Pwr Virus for AVFS ",
- return -EINVAL;);
- smu_data->avfs.avfs_btc_status = AVFS_BTC_FAILED;
- PP_ASSERT_WITH_CODE(0 == fiji_start_avfs_btc(hwmgr),
- "[AVFS][fiji_avfs_event_mgr] Failure at "
- "fiji_start_avfs_btc. AVFS Disabled",
- return -EINVAL;);
-
- smu_data->avfs.avfs_btc_status = AVFS_BTC_ENABLEAVFS;
- break;
- case AVFS_BTC_DISABLED: /* Do nothing */
- case AVFS_BTC_NOTSUPPORTED: /* Do nothing */
- case AVFS_BTC_ENABLEAVFS:
- break;
- default:
- pr_err("AVFS failed status is %x !\n", smu_data->avfs.avfs_btc_status);
- break;
- }
return 0;
}
@@ -309,8 +290,6 @@ static int fiji_start_smu(struct pp_hwmgr *hwmgr)
/* Only start SMC if SMC RAM is not running */
if (!(smu7_is_smc_ram_running(hwmgr)
|| cgs_is_virtualization_enabled(hwmgr->device))) {
- fiji_avfs_event_mgr(hwmgr, false);
-
/* Check if SMU is running in protected mode */
if (0 == PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device,
CGS_IND_REG__SMC,
@@ -323,7 +302,8 @@ static int fiji_start_smu(struct pp_hwmgr *hwmgr)
if (result)
return result;
}
- fiji_avfs_event_mgr(hwmgr, true);
+ if (fiji_avfs_event_mgr(hwmgr))
+ hwmgr->avfs_supported = false;
}
/* To initialize all clock gating before RLC loaded and running.*/
@@ -368,7 +348,6 @@ static bool fiji_is_hw_avfs_present(struct pp_hwmgr *hwmgr)
static int fiji_smu_init(struct pp_hwmgr *hwmgr)
{
- int i;
struct fiji_smumgr *fiji_priv = NULL;
fiji_priv = kzalloc(sizeof(struct fiji_smumgr), GFP_KERNEL);
@@ -378,11 +357,10 @@ static int fiji_smu_init(struct pp_hwmgr *hwmgr)
hwmgr->smu_backend = fiji_priv;
- if (smu7_init(hwmgr))
+ if (smu7_init(hwmgr)) {
+ kfree(fiji_priv);
return -EINVAL;
-
- for (i = 0; i < SMU73_MAX_LEVELS_GRAPHICS; i++)
- fiji_priv->activity_target[i] = 30;
+ }
return 0;
}
@@ -972,8 +950,7 @@ static int fiji_calculate_sclk_params(struct pp_hwmgr *hwmgr,
}
static int fiji_populate_single_graphic_level(struct pp_hwmgr *hwmgr,
- uint32_t clock, uint16_t sclk_al_threshold,
- struct SMU73_Discrete_GraphicsLevel *level)
+ uint32_t clock, struct SMU73_Discrete_GraphicsLevel *level)
{
int result;
/* PP_Clocks minClocks; */
@@ -981,12 +958,18 @@ static int fiji_populate_single_graphic_level(struct pp_hwmgr *hwmgr,
struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
struct phm_ppt_v1_information *table_info =
(struct phm_ppt_v1_information *)(hwmgr->pptable);
+ phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_table = NULL;
result = fiji_calculate_sclk_params(hwmgr, clock, level);
+ if (hwmgr->od_enabled)
+ vdd_dep_table = (phm_ppt_v1_clock_voltage_dependency_table *)&data->odn_dpm_table.vdd_dependency_on_sclk;
+ else
+ vdd_dep_table = table_info->vdd_dep_on_sclk;
+
/* populate graphics levels */
result = fiji_get_dependency_volt_by_clk(hwmgr,
- table_info->vdd_dep_on_sclk, clock,
+ vdd_dep_table, clock,
(uint32_t *)(&level->MinVoltage), &mvdd);
PP_ASSERT_WITH_CODE((0 == result),
"can not find VDDC voltage value for "
@@ -994,13 +977,13 @@ static int fiji_populate_single_graphic_level(struct pp_hwmgr *hwmgr,
return result);
level->SclkFrequency = clock;
- level->ActivityLevel = sclk_al_threshold;
+ level->ActivityLevel = data->current_profile_setting.sclk_activity;
level->CcPwrDynRm = 0;
level->CcPwrDynRm1 = 0;
level->EnabledForActivity = 0;
level->EnabledForThrottle = 1;
- level->UpHyst = 10;
- level->DownHyst = 0;
+ level->UpHyst = data->current_profile_setting.sclk_up_hyst;
+ level->DownHyst = data->current_profile_setting.sclk_down_hyst;
level->VoltageDownHyst = 0;
level->PowerThrottle = 0;
@@ -1057,7 +1040,6 @@ static int fiji_populate_all_graphic_levels(struct pp_hwmgr *hwmgr)
for (i = 0; i < dpm_table->sclk_table.count; i++) {
result = fiji_populate_single_graphic_level(hwmgr,
dpm_table->sclk_table.dpm_levels[i].value,
- (uint16_t)smu_data->activity_target[i],
&levels[i]);
if (result)
return result;
@@ -1202,10 +1184,16 @@ static int fiji_populate_single_memory_level(struct pp_hwmgr *hwmgr,
(struct phm_ppt_v1_information *)(hwmgr->pptable);
int result = 0;
uint32_t mclk_stutter_mode_threshold = 60000;
+ phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_table = NULL;
- if (table_info->vdd_dep_on_mclk) {
+ if (hwmgr->od_enabled)
+ vdd_dep_table = (phm_ppt_v1_clock_voltage_dependency_table *)&data->odn_dpm_table.vdd_dependency_on_mclk;
+ else
+ vdd_dep_table = table_info->vdd_dep_on_mclk;
+
+ if (vdd_dep_table) {
result = fiji_get_dependency_volt_by_clk(hwmgr,
- table_info->vdd_dep_on_mclk, clock,
+ vdd_dep_table, clock,
(uint32_t *)(&mem_level->MinVoltage), &mem_level->MinMvdd);
PP_ASSERT_WITH_CODE((0 == result),
"can not find MinVddc voltage value from memory "
@@ -1214,10 +1202,10 @@ static int fiji_populate_single_memory_level(struct pp_hwmgr *hwmgr,
mem_level->EnabledForThrottle = 1;
mem_level->EnabledForActivity = 0;
- mem_level->UpHyst = 0;
- mem_level->DownHyst = 100;
+ mem_level->UpHyst = data->current_profile_setting.mclk_up_hyst;
+ mem_level->DownHyst = data->current_profile_setting.mclk_down_hyst;
mem_level->VoltageDownHyst = 0;
- mem_level->ActivityLevel = (uint16_t)data->mclk_activity_target;
+ mem_level->ActivityLevel = data->current_profile_setting.mclk_activity;
mem_level->StutterEnable = false;
mem_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW;
@@ -1435,7 +1423,7 @@ static int fiji_populate_smc_acpi_level(struct pp_hwmgr *hwmgr,
table->MemoryACPILevel.DownHyst = 100;
table->MemoryACPILevel.VoltageDownHyst = 0;
table->MemoryACPILevel.ActivityLevel =
- PP_HOST_TO_SMC_US((uint16_t)data->mclk_activity_target);
+ PP_HOST_TO_SMC_US(data->current_profile_setting.mclk_activity);
table->MemoryACPILevel.StutterEnable = false;
CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MclkFrequency);
@@ -1799,7 +1787,7 @@ static int fiji_populate_clock_stretcher_data_table(struct pp_hwmgr *hwmgr)
phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_ClockStretcher);
PP_ASSERT_WITH_CODE(false,
- "Stretch Amount in PPTable not supported\n",
+ "Stretch Amount in PPTable not supported",
return -EINVAL);
}
@@ -1954,44 +1942,6 @@ static int fiji_init_arb_table_index(struct pp_hwmgr *hwmgr)
smu_data->smu7_data.arb_table_start, tmp, SMC_RAM_END);
}
-static int fiji_save_default_power_profile(struct pp_hwmgr *hwmgr)
-{
- struct fiji_smumgr *data = (struct fiji_smumgr *)(hwmgr->smu_backend);
- struct SMU73_Discrete_GraphicsLevel *levels =
- data->smc_state_table.GraphicsLevel;
- unsigned min_level = 1;
-
- hwmgr->default_gfx_power_profile.activity_threshold =
- be16_to_cpu(levels[0].ActivityLevel);
- hwmgr->default_gfx_power_profile.up_hyst = levels[0].UpHyst;
- hwmgr->default_gfx_power_profile.down_hyst = levels[0].DownHyst;
- hwmgr->default_gfx_power_profile.type = AMD_PP_GFX_PROFILE;
-
- hwmgr->default_compute_power_profile = hwmgr->default_gfx_power_profile;
- hwmgr->default_compute_power_profile.type = AMD_PP_COMPUTE_PROFILE;
-
- /* Workaround compute SDMA instability: disable lowest SCLK
- * DPM level. Optimize compute power profile: Use only highest
- * 2 power levels (if more than 2 are available), Hysteresis:
- * 0ms up, 5ms down
- */
- if (data->smc_state_table.GraphicsDpmLevelCount > 2)
- min_level = data->smc_state_table.GraphicsDpmLevelCount - 2;
- else if (data->smc_state_table.GraphicsDpmLevelCount == 2)
- min_level = 1;
- else
- min_level = 0;
- hwmgr->default_compute_power_profile.min_sclk =
- be32_to_cpu(levels[min_level].SclkFrequency);
- hwmgr->default_compute_power_profile.up_hyst = 0;
- hwmgr->default_compute_power_profile.down_hyst = 5;
-
- hwmgr->gfx_power_profile = hwmgr->default_gfx_power_profile;
- hwmgr->compute_power_profile = hwmgr->default_compute_power_profile;
-
- return 0;
-}
-
static int fiji_setup_dpm_led_config(struct pp_hwmgr *hwmgr)
{
pp_atomctrl_voltage_table param_led_dpm;
@@ -2141,7 +2091,7 @@ static int fiji_init_smc_table(struct pp_hwmgr *hwmgr)
result = fiji_populate_vr_config(hwmgr, table);
PP_ASSERT_WITH_CODE(0 == result,
"Failed to populate VRConfig setting!", return result);
-
+ data->vr_config = table->VRConfig;
table->ThermGpio = 17;
table->SclkStepSize = 0x4000;
@@ -2232,8 +2182,6 @@ static int fiji_init_smc_table(struct pp_hwmgr *hwmgr)
PP_ASSERT_WITH_CODE(0 == result,
"Failed to setup dpm led config", return result);
- fiji_save_default_power_profile(hwmgr);
-
return 0;
}
@@ -2309,7 +2257,7 @@ static int fiji_thermal_setup_fan_table(struct pp_hwmgr *hwmgr)
fan_table.TempRespLim = cpu_to_be16(5);
- reference_clock = smu7_get_xclk(hwmgr);
+ reference_clock = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev);
fan_table.RefreshPeriod = cpu_to_be32((hwmgr->
thermal_controller.advanceFanControlParameters.ulCycleDelay *
@@ -2349,19 +2297,12 @@ static int fiji_thermal_setup_fan_table(struct pp_hwmgr *hwmgr)
static int fiji_thermal_avfs_enable(struct pp_hwmgr *hwmgr)
{
- int ret;
- struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend);
-
- if (smu_data->avfs.avfs_btc_status != AVFS_BTC_ENABLEAVFS)
+ if (!hwmgr->avfs_supported)
return 0;
- ret = smum_send_msg_to_smc(hwmgr, PPSMC_MSG_EnableAvfs);
-
- if (!ret)
- /* If this param is not changed, this function could fire unnecessarily */
- smu_data->avfs.avfs_btc_status = AVFS_BTC_COMPLETED_PREVIOUSLY;
+ smum_send_msg_to_smc(hwmgr, PPSMC_MSG_EnableAvfs);
- return ret;
+ return 0;
}
static int fiji_program_mem_timing_parameters(struct pp_hwmgr *hwmgr)
@@ -2688,29 +2629,100 @@ static bool fiji_is_dpm_running(struct pp_hwmgr *hwmgr)
? true : false;
}
-static int fiji_populate_requested_graphic_levels(struct pp_hwmgr *hwmgr,
- struct amd_pp_profile *request)
+static int fiji_update_dpm_settings(struct pp_hwmgr *hwmgr,
+ void *profile_setting)
{
+ struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
struct fiji_smumgr *smu_data = (struct fiji_smumgr *)
(hwmgr->smu_backend);
+ struct profile_mode_setting *setting;
struct SMU73_Discrete_GraphicsLevel *levels =
smu_data->smc_state_table.GraphicsLevel;
uint32_t array = smu_data->smu7_data.dpm_table_start +
offsetof(SMU73_Discrete_DpmTable, GraphicsLevel);
- uint32_t array_size = sizeof(struct SMU73_Discrete_GraphicsLevel) *
- SMU73_MAX_LEVELS_GRAPHICS;
+
+ uint32_t mclk_array = smu_data->smu7_data.dpm_table_start +
+ offsetof(SMU73_Discrete_DpmTable, MemoryLevel);
+ struct SMU73_Discrete_MemoryLevel *mclk_levels =
+ smu_data->smc_state_table.MemoryLevel;
uint32_t i;
+ uint32_t offset, up_hyst_offset, down_hyst_offset, clk_activity_offset, tmp;
- for (i = 0; i < smu_data->smc_state_table.GraphicsDpmLevelCount; i++) {
- levels[i].ActivityLevel =
- cpu_to_be16(request->activity_threshold);
- levels[i].EnabledForActivity = 1;
- levels[i].UpHyst = request->up_hyst;
- levels[i].DownHyst = request->down_hyst;
+ if (profile_setting == NULL)
+ return -EINVAL;
+
+ setting = (struct profile_mode_setting *)profile_setting;
+
+ if (setting->bupdate_sclk) {
+ if (!data->sclk_dpm_key_disabled)
+ smum_send_msg_to_smc(hwmgr, PPSMC_MSG_SCLKDPM_FreezeLevel);
+ for (i = 0; i < smu_data->smc_state_table.GraphicsDpmLevelCount; i++) {
+ if (levels[i].ActivityLevel !=
+ cpu_to_be16(setting->sclk_activity)) {
+ levels[i].ActivityLevel = cpu_to_be16(setting->sclk_activity);
+
+ clk_activity_offset = array + (sizeof(SMU73_Discrete_GraphicsLevel) * i)
+ + offsetof(SMU73_Discrete_GraphicsLevel, ActivityLevel);
+ offset = clk_activity_offset & ~0x3;
+ tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset));
+ tmp = phm_set_field_to_u32(clk_activity_offset, tmp, levels[i].ActivityLevel, sizeof(uint16_t));
+ cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp));
+
+ }
+ if (levels[i].UpHyst != setting->sclk_up_hyst ||
+ levels[i].DownHyst != setting->sclk_down_hyst) {
+ levels[i].UpHyst = setting->sclk_up_hyst;
+ levels[i].DownHyst = setting->sclk_down_hyst;
+ up_hyst_offset = array + (sizeof(SMU73_Discrete_GraphicsLevel) * i)
+ + offsetof(SMU73_Discrete_GraphicsLevel, UpHyst);
+ down_hyst_offset = array + (sizeof(SMU73_Discrete_GraphicsLevel) * i)
+ + offsetof(SMU73_Discrete_GraphicsLevel, DownHyst);
+ offset = up_hyst_offset & ~0x3;
+ tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset));
+ tmp = phm_set_field_to_u32(up_hyst_offset, tmp, levels[i].UpHyst, sizeof(uint8_t));
+ tmp = phm_set_field_to_u32(down_hyst_offset, tmp, levels[i].DownHyst, sizeof(uint8_t));
+ cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp));
+ }
+ }
+ if (!data->sclk_dpm_key_disabled)
+ smum_send_msg_to_smc(hwmgr, PPSMC_MSG_SCLKDPM_UnfreezeLevel);
}
- return smu7_copy_bytes_to_smc(hwmgr, array, (uint8_t *)levels,
- array_size, SMC_RAM_END);
+ if (setting->bupdate_mclk) {
+ if (!data->mclk_dpm_key_disabled)
+ smum_send_msg_to_smc(hwmgr, PPSMC_MSG_MCLKDPM_FreezeLevel);
+ for (i = 0; i < smu_data->smc_state_table.MemoryDpmLevelCount; i++) {
+ if (mclk_levels[i].ActivityLevel !=
+ cpu_to_be16(setting->mclk_activity)) {
+ mclk_levels[i].ActivityLevel = cpu_to_be16(setting->mclk_activity);
+
+ clk_activity_offset = mclk_array + (sizeof(SMU73_Discrete_MemoryLevel) * i)
+ + offsetof(SMU73_Discrete_MemoryLevel, ActivityLevel);
+ offset = clk_activity_offset & ~0x3;
+ tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset));
+ tmp = phm_set_field_to_u32(clk_activity_offset, tmp, mclk_levels[i].ActivityLevel, sizeof(uint16_t));
+ cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp));
+
+ }
+ if (mclk_levels[i].UpHyst != setting->mclk_up_hyst ||
+ mclk_levels[i].DownHyst != setting->mclk_down_hyst) {
+ mclk_levels[i].UpHyst = setting->mclk_up_hyst;
+ mclk_levels[i].DownHyst = setting->mclk_down_hyst;
+ up_hyst_offset = mclk_array + (sizeof(SMU73_Discrete_MemoryLevel) * i)
+ + offsetof(SMU73_Discrete_MemoryLevel, UpHyst);
+ down_hyst_offset = mclk_array + (sizeof(SMU73_Discrete_MemoryLevel) * i)
+ + offsetof(SMU73_Discrete_MemoryLevel, DownHyst);
+ offset = up_hyst_offset & ~0x3;
+ tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset));
+ tmp = phm_set_field_to_u32(up_hyst_offset, tmp, mclk_levels[i].UpHyst, sizeof(uint8_t));
+ tmp = phm_set_field_to_u32(down_hyst_offset, tmp, mclk_levels[i].DownHyst, sizeof(uint8_t));
+ cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp));
+ }
+ }
+ if (!data->mclk_dpm_key_disabled)
+ smum_send_msg_to_smc(hwmgr, PPSMC_MSG_MCLKDPM_UnfreezeLevel);
+ }
+ return 0;
}
const struct pp_smumgr_func fiji_smu_funcs = {
@@ -2736,6 +2748,6 @@ const struct pp_smumgr_func fiji_smu_funcs = {
.get_mac_definition = fiji_get_mac_definition,
.initialize_mc_reg_table = fiji_initialize_mc_reg_table,
.is_dpm_running = fiji_is_dpm_running,
- .populate_requested_graphic_levels = fiji_populate_requested_graphic_levels,
.is_hw_avfs_present = fiji_is_hw_avfs_present,
+ .update_dpm_settings = fiji_update_dpm_settings,
};
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.h b/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.h
index 279647772578..6d3746268ccf 100644
--- a/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.h
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.h
@@ -43,8 +43,6 @@ struct fiji_smumgr {
struct SMU73_Discrete_Ulv ulv_setting;
struct SMU73_Discrete_PmFuses power_tune_table;
const struct fiji_pt_defaults *power_tune_defaults;
- uint32_t activity_target[SMU73_MAX_LEVELS_GRAPHICS];
-
};
#endif
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smumgr.c
index 125312691f75..d4bb934e7334 100644
--- a/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smumgr.c
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smumgr.c
@@ -262,7 +262,6 @@ static int iceland_start_smu(struct pp_hwmgr *hwmgr)
static int iceland_smu_init(struct pp_hwmgr *hwmgr)
{
- int i;
struct iceland_smumgr *iceland_priv = NULL;
iceland_priv = kzalloc(sizeof(struct iceland_smumgr), GFP_KERNEL);
@@ -272,11 +271,10 @@ static int iceland_smu_init(struct pp_hwmgr *hwmgr)
hwmgr->smu_backend = iceland_priv;
- if (smu7_init(hwmgr))
+ if (smu7_init(hwmgr)) {
+ kfree(iceland_priv);
return -EINVAL;
-
- for (i = 0; i < SMU71_MAX_LEVELS_GRAPHICS; i++)
- iceland_priv->activity_target[i] = 30;
+ }
return 0;
}
@@ -285,13 +283,10 @@ static int iceland_smu_init(struct pp_hwmgr *hwmgr)
static void iceland_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr)
{
struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend);
- struct cgs_system_info sys_info = {0};
+ struct amdgpu_device *adev = hwmgr->adev;
uint32_t dev_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);
- dev_id = (uint32_t)sys_info.value;
+ dev_id = adev->pdev->device;
switch (dev_id) {
case DEVICE_ID_VI_ICELAND_M_6900:
@@ -546,7 +541,7 @@ static int iceland_get_std_voltage_value_sidd(struct pp_hwmgr *hwmgr,
/* SCLK/VDDC Dependency Table has to exist. */
PP_ASSERT_WITH_CODE(NULL != hwmgr->dyn_state.vddc_dependency_on_sclk,
- "The SCLK/VDDC Dependency Table does not exist.\n",
+ "The SCLK/VDDC Dependency Table does not exist.",
return -EINVAL);
if (NULL == hwmgr->dyn_state.cac_leakage_table) {
@@ -898,7 +893,6 @@ static int iceland_populate_phase_value_based_on_sclk(struct pp_hwmgr *hwmgr,
static int iceland_populate_single_graphic_level(struct pp_hwmgr *hwmgr,
uint32_t engine_clock,
- uint16_t sclk_activity_level_threshold,
SMU71_Discrete_GraphicsLevel *graphic_level)
{
int result;
@@ -924,7 +918,7 @@ static int iceland_populate_single_graphic_level(struct pp_hwmgr *hwmgr,
&graphic_level->MinVddcPhases);
/* Indicates maximum activity level for this performance level. 50% for now*/
- graphic_level->ActivityLevel = sclk_activity_level_threshold;
+ graphic_level->ActivityLevel = data->current_profile_setting.sclk_activity;
graphic_level->CcPwrDynRm = 0;
graphic_level->CcPwrDynRm1 = 0;
@@ -932,8 +926,8 @@ static int iceland_populate_single_graphic_level(struct pp_hwmgr *hwmgr,
graphic_level->EnabledForActivity = 0;
/* this level can be used for throttling.*/
graphic_level->EnabledForThrottle = 1;
- graphic_level->UpHyst = 0;
- graphic_level->DownHyst = 100;
+ graphic_level->UpHyst = data->current_profile_setting.sclk_up_hyst;
+ graphic_level->DownHyst = data->current_profile_setting.sclk_down_hyst;
graphic_level->VoltageDownHyst = 0;
graphic_level->PowerThrottle = 0;
@@ -989,7 +983,6 @@ static int iceland_populate_all_graphic_levels(struct pp_hwmgr *hwmgr)
for (i = 0; i < dpm_table->sclk_table.count; i++) {
result = iceland_populate_single_graphic_level(hwmgr,
dpm_table->sclk_table.dpm_levels[i].value,
- (uint16_t)smu_data->activity_target[i],
&(smu_data->smc_state_table.GraphicsLevel[i]));
if (result != 0)
return result;
@@ -1275,12 +1268,12 @@ static int iceland_populate_single_memory_level(
memory_level->EnabledForThrottle = 1;
memory_level->EnabledForActivity = 0;
- memory_level->UpHyst = 0;
- memory_level->DownHyst = 100;
+ memory_level->UpHyst = data->current_profile_setting.mclk_up_hyst;
+ memory_level->DownHyst = data->current_profile_setting.mclk_down_hyst;
memory_level->VoltageDownHyst = 0;
/* Indicates maximum activity level for this performance level.*/
- memory_level->ActivityLevel = (uint16_t)data->mclk_activity_target;
+ memory_level->ActivityLevel = data->current_profile_setting.mclk_activity;
memory_level->StutterEnable = 0;
memory_level->StrobeEnable = 0;
memory_level->EdcReadEnable = 0;
@@ -1561,7 +1554,7 @@ static int iceland_populate_smc_acpi_level(struct pp_hwmgr *hwmgr,
table->MemoryACPILevel.DownHyst = 100;
table->MemoryACPILevel.VoltageDownHyst = 0;
/* Indicates maximum activity level for this performance level.*/
- table->MemoryACPILevel.ActivityLevel = PP_HOST_TO_SMC_US((uint16_t)data->mclk_activity_target);
+ table->MemoryACPILevel.ActivityLevel = PP_HOST_TO_SMC_US(data->current_profile_setting.mclk_activity);
table->MemoryACPILevel.StutterEnable = 0;
table->MemoryACPILevel.StrobeEnable = 0;
@@ -2165,7 +2158,7 @@ int iceland_thermal_setup_fan_table(struct pp_hwmgr *hwmgr)
fan_table.TempRespLim = cpu_to_be16(5);
- reference_clock = smu7_get_xclk(hwmgr);
+ reference_clock = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev);
fan_table.RefreshPeriod = cpu_to_be32((hwmgr->thermal_controller.advanceFanControlParameters.ulCycleDelay * reference_clock) / 1600);
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smumgr.h b/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smumgr.h
index 802472530d34..f32c506779c9 100644
--- a/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smumgr.h
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smumgr.h
@@ -65,7 +65,6 @@ struct iceland_smumgr {
const struct iceland_pt_defaults *power_tune_defaults;
SMU71_Discrete_MCRegisters mc_regs;
struct iceland_mc_reg_table mc_reg_table;
- uint32_t activity_target[SMU71_MAX_LEVELS_GRAPHICS];
};
#endif
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c
index cdb47657b567..997a777dd35b 100644
--- a/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c
@@ -99,13 +99,13 @@ static int polaris10_perform_btc(struct pp_hwmgr *hwmgr)
int result = 0;
struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend);
- if (0 != smu_data->avfs.avfs_btc_param) {
- if (0 != smu7_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_PerformBtc, smu_data->avfs.avfs_btc_param)) {
+ if (0 != smu_data->avfs_btc_param) {
+ if (0 != smu7_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_PerformBtc, smu_data->avfs_btc_param)) {
pr_info("[AVFS][SmuPolaris10_PerformBtc] PerformBTC SMU msg failed");
result = -1;
}
}
- if (smu_data->avfs.avfs_btc_param > 1) {
+ if (smu_data->avfs_btc_param > 1) {
/* Soft-Reset to reset the engine before loading uCode */
/* halt */
cgs_write_register(hwmgr->device, mmCP_MEC_CNTL, 0x50000000);
@@ -172,47 +172,28 @@ static int polaris10_setup_graphics_level_structure(struct pp_hwmgr *hwmgr)
}
-static int
-polaris10_avfs_event_mgr(struct pp_hwmgr *hwmgr, bool SMU_VFT_INTACT)
+static int polaris10_avfs_event_mgr(struct pp_hwmgr *hwmgr)
{
struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend);
- switch (smu_data->avfs.avfs_btc_status) {
- case AVFS_BTC_COMPLETED_PREVIOUSLY:
- break;
-
- case AVFS_BTC_BOOT: /* Cold Boot State - Post SMU Start */
-
- smu_data->avfs.avfs_btc_status = AVFS_BTC_DPMTABLESETUP_FAILED;
- PP_ASSERT_WITH_CODE(0 == polaris10_setup_graphics_level_structure(hwmgr),
- "[AVFS][Polaris10_AVFSEventMgr] Could not Copy Graphics Level table over to SMU",
- return -EINVAL);
-
- if (smu_data->avfs.avfs_btc_param > 1) {
- pr_info("[AVFS][Polaris10_AVFSEventMgr] AC BTC has not been successfully verified on Fiji. There may be in this setting.");
- smu_data->avfs.avfs_btc_status = AVFS_BTC_VIRUS_FAIL;
- PP_ASSERT_WITH_CODE(0 == smu7_setup_pwr_virus(hwmgr),
- "[AVFS][Polaris10_AVFSEventMgr] Could not setup Pwr Virus for AVFS ",
- return -EINVAL);
- }
-
- smu_data->avfs.avfs_btc_status = AVFS_BTC_FAILED;
- PP_ASSERT_WITH_CODE(0 == polaris10_perform_btc(hwmgr),
- "[AVFS][Polaris10_AVFSEventMgr] Failure at SmuPolaris10_PerformBTC. AVFS Disabled",
- return -EINVAL);
- smu_data->avfs.avfs_btc_status = AVFS_BTC_ENABLEAVFS;
- break;
+ if (!hwmgr->avfs_supported)
+ return 0;
- case AVFS_BTC_DISABLED:
- case AVFS_BTC_ENABLEAVFS:
- case AVFS_BTC_NOTSUPPORTED:
- break;
+ PP_ASSERT_WITH_CODE(0 == polaris10_setup_graphics_level_structure(hwmgr),
+ "[AVFS][Polaris10_AVFSEventMgr] Could not Copy Graphics Level table over to SMU",
+ return -EINVAL);
- default:
- pr_err("AVFS failed status is %x!\n", smu_data->avfs.avfs_btc_status);
- break;
+ if (smu_data->avfs_btc_param > 1) {
+ pr_info("[AVFS][Polaris10_AVFSEventMgr] AC BTC has not been successfully verified on Fiji. There may be in this setting.");
+ PP_ASSERT_WITH_CODE(0 == smu7_setup_pwr_virus(hwmgr),
+ "[AVFS][Polaris10_AVFSEventMgr] Could not setup Pwr Virus for AVFS ",
+ return -EINVAL);
}
+ PP_ASSERT_WITH_CODE(0 == polaris10_perform_btc(hwmgr),
+ "[AVFS][Polaris10_AVFSEventMgr] Failure at SmuPolaris10_PerformBTC. AVFS Disabled",
+ return -EINVAL);
+
return 0;
}
@@ -312,11 +293,10 @@ static int polaris10_start_smu(struct pp_hwmgr *hwmgr)
{
int result = 0;
struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend);
- bool SMU_VFT_INTACT;
/* Only start SMC if SMC RAM is not running */
- if (!smu7_is_smc_ram_running(hwmgr)) {
- SMU_VFT_INTACT = false;
+ if (!(smu7_is_smc_ram_running(hwmgr)
+ || cgs_is_virtualization_enabled(hwmgr->device))) {
smu_data->protected_mode = (uint8_t) (PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMU_FIRMWARE, SMU_MODE));
smu_data->smu7_data.security_hard_key = (uint8_t) (PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMU_FIRMWARE, SMU_SEL));
@@ -337,11 +317,9 @@ static int polaris10_start_smu(struct pp_hwmgr *hwmgr)
if (result != 0)
PP_ASSERT_WITH_CODE(0, "Failed to load SMU ucode.", return result);
- polaris10_avfs_event_mgr(hwmgr, true);
- } else
- SMU_VFT_INTACT = true; /*Driver went offline but SMU was still alive and contains the VFT table */
+ polaris10_avfs_event_mgr(hwmgr);
+ }
- polaris10_avfs_event_mgr(hwmgr, SMU_VFT_INTACT);
/* Setup SoftRegsStart here for register lookup in case DummyBackEnd is used and ProcessFirmwareHeader is not executed */
smu7_read_smc_sram_dword(hwmgr, SMU7_FIRMWARE_HEADER_LOCATION + offsetof(SMU74_Firmware_Header, SoftRegisters),
&(smu_data->smu7_data.soft_regs_start), 0x40000);
@@ -366,7 +344,6 @@ static bool polaris10_is_hw_avfs_present(struct pp_hwmgr *hwmgr)
static int polaris10_smu_init(struct pp_hwmgr *hwmgr)
{
struct polaris10_smumgr *smu_data;
- int i;
smu_data = kzalloc(sizeof(struct polaris10_smumgr), GFP_KERNEL);
if (smu_data == NULL)
@@ -374,11 +351,10 @@ static int polaris10_smu_init(struct pp_hwmgr *hwmgr)
hwmgr->smu_backend = smu_data;
- if (smu7_init(hwmgr))
+ if (smu7_init(hwmgr)) {
+ kfree(smu_data);
return -EINVAL;
-
- for (i = 0; i < SMU74_MAX_LEVELS_GRAPHICS; i++)
- smu_data->activity_target[i] = PPPOLARIS10_TARGETACTIVITY_DFLT;
+ }
return 0;
}
@@ -837,7 +813,7 @@ static void polaris10_get_sclk_range_table(struct pp_hwmgr *hwmgr,
struct pp_atom_ctrl_sclk_range_table range_table_from_vbios = { { {0} } };
- ref_clk = smu7_get_xclk(hwmgr);
+ ref_clk = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev);
if (0 == atomctrl_get_smc_sclk_range_table(hwmgr, &range_table_from_vbios)) {
for (i = 0; i < NUM_SCLK_RANGE; i++) {
@@ -902,7 +878,7 @@ static int polaris10_calculate_sclk_params(struct pp_hwmgr *hwmgr,
return result;
}
- ref_clock = smu7_get_xclk(hwmgr);
+ ref_clock = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev);
for (i = 0; i < NUM_SCLK_RANGE; i++) {
if (clock > smu_data->range_table[i].trans_lower_frequency
@@ -938,8 +914,7 @@ static int polaris10_calculate_sclk_params(struct pp_hwmgr *hwmgr,
}
static int polaris10_populate_single_graphic_level(struct pp_hwmgr *hwmgr,
- uint32_t clock, uint16_t sclk_al_threshold,
- struct SMU74_Discrete_GraphicsLevel *level)
+ uint32_t clock, struct SMU74_Discrete_GraphicsLevel *level)
{
int result;
/* PP_Clocks minClocks; */
@@ -948,26 +923,32 @@ static int polaris10_populate_single_graphic_level(struct pp_hwmgr *hwmgr,
struct phm_ppt_v1_information *table_info =
(struct phm_ppt_v1_information *)(hwmgr->pptable);
SMU_SclkSetting curr_sclk_setting = { 0 };
+ phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_table = NULL;
result = polaris10_calculate_sclk_params(hwmgr, clock, &curr_sclk_setting);
+ if (hwmgr->od_enabled)
+ vdd_dep_table = (phm_ppt_v1_clock_voltage_dependency_table *)&data->odn_dpm_table.vdd_dependency_on_sclk;
+ else
+ vdd_dep_table = table_info->vdd_dep_on_sclk;
+
/* populate graphics levels */
result = polaris10_get_dependency_volt_by_clk(hwmgr,
- table_info->vdd_dep_on_sclk, clock,
+ vdd_dep_table, clock,
&level->MinVoltage, &mvdd);
PP_ASSERT_WITH_CODE((0 == result),
"can not find VDDC voltage value for "
"VDDC engine clock dependency table",
return result);
- level->ActivityLevel = sclk_al_threshold;
+ level->ActivityLevel = data->current_profile_setting.sclk_activity;
level->CcPwrDynRm = 0;
level->CcPwrDynRm1 = 0;
level->EnabledForActivity = 0;
level->EnabledForThrottle = 1;
- level->UpHyst = 10;
- level->DownHyst = 0;
+ level->UpHyst = data->current_profile_setting.sclk_up_hyst;
+ level->DownHyst = data->current_profile_setting.sclk_down_hyst;
level->VoltageDownHyst = 0;
level->PowerThrottle = 0;
data->display_timing.min_clock_in_sr = hwmgr->display_config.min_core_set_clock_in_sr;
@@ -1031,7 +1012,6 @@ static int polaris10_populate_all_graphic_levels(struct pp_hwmgr *hwmgr)
result = polaris10_populate_single_graphic_level(hwmgr,
dpm_table->sclk_table.dpm_levels[i].value,
- (uint16_t)smu_data->activity_target[i],
&(smu_data->smc_state_table.GraphicsLevel[i]));
if (result)
return result;
@@ -1107,12 +1087,18 @@ static int polaris10_populate_single_memory_level(struct pp_hwmgr *hwmgr,
int result = 0;
struct cgs_display_info info = {0, 0, NULL};
uint32_t mclk_stutter_mode_threshold = 40000;
+ phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_table = NULL;
cgs_get_active_displays_info(hwmgr->device, &info);
- if (table_info->vdd_dep_on_mclk) {
+ if (hwmgr->od_enabled)
+ vdd_dep_table = (phm_ppt_v1_clock_voltage_dependency_table *)&data->odn_dpm_table.vdd_dependency_on_mclk;
+ else
+ vdd_dep_table = table_info->vdd_dep_on_mclk;
+
+ if (vdd_dep_table) {
result = polaris10_get_dependency_volt_by_clk(hwmgr,
- table_info->vdd_dep_on_mclk, clock,
+ vdd_dep_table, clock,
&mem_level->MinVoltage, &mem_level->MinMvdd);
PP_ASSERT_WITH_CODE((0 == result),
"can not find MinVddc voltage value from memory "
@@ -1122,10 +1108,10 @@ static int polaris10_populate_single_memory_level(struct pp_hwmgr *hwmgr,
mem_level->MclkFrequency = clock;
mem_level->EnabledForThrottle = 1;
mem_level->EnabledForActivity = 0;
- mem_level->UpHyst = 0;
- mem_level->DownHyst = 100;
+ mem_level->UpHyst = data->current_profile_setting.mclk_up_hyst;
+ mem_level->DownHyst = data->current_profile_setting.mclk_down_hyst;
mem_level->VoltageDownHyst = 0;
- mem_level->ActivityLevel = (uint16_t)data->mclk_activity_target;
+ mem_level->ActivityLevel = data->current_profile_setting.mclk_activity;
mem_level->StutterEnable = false;
mem_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW;
@@ -1306,7 +1292,7 @@ static int polaris10_populate_smc_acpi_level(struct pp_hwmgr *hwmgr,
table->MemoryACPILevel.DownHyst = 100;
table->MemoryACPILevel.VoltageDownHyst = 0;
table->MemoryACPILevel.ActivityLevel =
- PP_HOST_TO_SMC_US((uint16_t)data->mclk_activity_target);
+ PP_HOST_TO_SMC_US(data->current_profile_setting.mclk_activity);
CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MclkFrequency);
CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MinVoltage);
@@ -1652,7 +1638,7 @@ static int polaris10_populate_clock_stretcher_data_table(struct pp_hwmgr *hwmgr)
phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_ClockStretcher);
PP_ASSERT_WITH_CODE(false,
- "Stretch Amount in PPTable not supported\n",
+ "Stretch Amount in PPTable not supported",
return -EINVAL);
}
@@ -1726,8 +1712,8 @@ static int polaris10_populate_avfs_parameters(struct pp_hwmgr *hwmgr)
table_info->vdd_dep_on_sclk;
- if (((struct smu7_smumgr *)smu_data)->avfs.avfs_btc_status == AVFS_BTC_NOTSUPPORTED)
- return result;
+ if (!hwmgr->avfs_supported)
+ return 0;
result = atomctrl_get_avfs_information(hwmgr, &avfs_params);
@@ -1834,42 +1820,6 @@ static void polaris10_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr)
}
-static void polaris10_save_default_power_profile(struct pp_hwmgr *hwmgr)
-{
- struct polaris10_smumgr *data = (struct polaris10_smumgr *)(hwmgr->smu_backend);
- struct SMU74_Discrete_GraphicsLevel *levels =
- data->smc_state_table.GraphicsLevel;
- unsigned min_level = 1;
-
- hwmgr->default_gfx_power_profile.activity_threshold =
- be16_to_cpu(levels[0].ActivityLevel);
- hwmgr->default_gfx_power_profile.up_hyst = levels[0].UpHyst;
- hwmgr->default_gfx_power_profile.down_hyst = levels[0].DownHyst;
- hwmgr->default_gfx_power_profile.type = AMD_PP_GFX_PROFILE;
-
- hwmgr->default_compute_power_profile = hwmgr->default_gfx_power_profile;
- hwmgr->default_compute_power_profile.type = AMD_PP_COMPUTE_PROFILE;
-
- /* Workaround compute SDMA instability: disable lowest SCLK
- * DPM level. Optimize compute power profile: Use only highest
- * 2 power levels (if more than 2 are available), Hysteresis:
- * 0ms up, 5ms down
- */
- if (data->smc_state_table.GraphicsDpmLevelCount > 2)
- min_level = data->smc_state_table.GraphicsDpmLevelCount - 2;
- else if (data->smc_state_table.GraphicsDpmLevelCount == 2)
- min_level = 1;
- else
- min_level = 0;
- hwmgr->default_compute_power_profile.min_sclk =
- be32_to_cpu(levels[min_level].SclkSetting.SclkFrequency);
- hwmgr->default_compute_power_profile.up_hyst = 0;
- hwmgr->default_compute_power_profile.down_hyst = 5;
-
- hwmgr->gfx_power_profile = hwmgr->default_gfx_power_profile;
- hwmgr->compute_power_profile = hwmgr->default_compute_power_profile;
-}
-
static int polaris10_init_smc_table(struct pp_hwmgr *hwmgr)
{
int result;
@@ -1991,7 +1941,7 @@ static int polaris10_init_smc_table(struct pp_hwmgr *hwmgr)
result = polaris10_populate_vr_config(hwmgr, table);
PP_ASSERT_WITH_CODE(0 == result,
"Failed to populate VRConfig setting!", return result);
-
+ hw_data->vr_config = table->VRConfig;
table->ThermGpio = 17;
table->SclkStepSize = 0x4000;
@@ -2084,8 +2034,6 @@ static int polaris10_init_smc_table(struct pp_hwmgr *hwmgr)
PP_ASSERT_WITH_CODE(0 == result,
"Failed to populate PM fuses to SMC memory!", return result);
- polaris10_save_default_power_profile(hwmgr);
-
return 0;
}
@@ -2102,24 +2050,17 @@ static int polaris10_program_mem_timing_parameters(struct pp_hwmgr *hwmgr)
int polaris10_thermal_avfs_enable(struct pp_hwmgr *hwmgr)
{
- int ret;
- struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend);
struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
- if (smu_data->avfs.avfs_btc_status == AVFS_BTC_NOTSUPPORTED)
+ if (!hwmgr->avfs_supported)
return 0;
- ret = smum_send_msg_to_smc_with_parameter(hwmgr,
+ smum_send_msg_to_smc_with_parameter(hwmgr,
PPSMC_MSG_SetGBDroopSettings, data->avfs_vdroop_override_setting);
- ret = (smum_send_msg_to_smc(hwmgr, PPSMC_MSG_EnableAvfs) == 0) ?
- 0 : -1;
-
- if (!ret)
- /* If this param is not changed, this function could fire unnecessarily */
- smu_data->avfs.avfs_btc_status = AVFS_BTC_COMPLETED_PREVIOUSLY;
+ smum_send_msg_to_smc(hwmgr, PPSMC_MSG_EnableAvfs);
- return ret;
+ return 0;
}
static int polaris10_thermal_setup_fan_table(struct pp_hwmgr *hwmgr)
@@ -2193,7 +2134,7 @@ static int polaris10_thermal_setup_fan_table(struct pp_hwmgr *hwmgr)
fan_table.TempRespLim = cpu_to_be16(5);
- reference_clock = smu7_get_xclk(hwmgr);
+ reference_clock = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev);
fan_table.RefreshPeriod = cpu_to_be32((hwmgr->
thermal_controller.advanceFanControlParameters.ulCycleDelay *
@@ -2544,29 +2485,100 @@ static bool polaris10_is_dpm_running(struct pp_hwmgr *hwmgr)
? true : false;
}
-static int polaris10_populate_requested_graphic_levels(struct pp_hwmgr *hwmgr,
- struct amd_pp_profile *request)
+static int polaris10_update_dpm_settings(struct pp_hwmgr *hwmgr,
+ void *profile_setting)
{
+ struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)
(hwmgr->smu_backend);
+ struct profile_mode_setting *setting;
struct SMU74_Discrete_GraphicsLevel *levels =
smu_data->smc_state_table.GraphicsLevel;
uint32_t array = smu_data->smu7_data.dpm_table_start +
offsetof(SMU74_Discrete_DpmTable, GraphicsLevel);
- uint32_t array_size = sizeof(struct SMU74_Discrete_GraphicsLevel) *
- SMU74_MAX_LEVELS_GRAPHICS;
+
+ uint32_t mclk_array = smu_data->smu7_data.dpm_table_start +
+ offsetof(SMU74_Discrete_DpmTable, MemoryLevel);
+ struct SMU74_Discrete_MemoryLevel *mclk_levels =
+ smu_data->smc_state_table.MemoryLevel;
uint32_t i;
+ uint32_t offset, up_hyst_offset, down_hyst_offset, clk_activity_offset, tmp;
- for (i = 0; i < smu_data->smc_state_table.GraphicsDpmLevelCount; i++) {
- levels[i].ActivityLevel =
- cpu_to_be16(request->activity_threshold);
- levels[i].EnabledForActivity = 1;
- levels[i].UpHyst = request->up_hyst;
- levels[i].DownHyst = request->down_hyst;
+ if (profile_setting == NULL)
+ return -EINVAL;
+
+ setting = (struct profile_mode_setting *)profile_setting;
+
+ if (setting->bupdate_sclk) {
+ if (!data->sclk_dpm_key_disabled)
+ smum_send_msg_to_smc(hwmgr, PPSMC_MSG_SCLKDPM_FreezeLevel);
+ for (i = 0; i < smu_data->smc_state_table.GraphicsDpmLevelCount; i++) {
+ if (levels[i].ActivityLevel !=
+ cpu_to_be16(setting->sclk_activity)) {
+ levels[i].ActivityLevel = cpu_to_be16(setting->sclk_activity);
+
+ clk_activity_offset = array + (sizeof(SMU74_Discrete_GraphicsLevel) * i)
+ + offsetof(SMU74_Discrete_GraphicsLevel, ActivityLevel);
+ offset = clk_activity_offset & ~0x3;
+ tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset));
+ tmp = phm_set_field_to_u32(clk_activity_offset, tmp, levels[i].ActivityLevel, sizeof(uint16_t));
+ cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp));
+
+ }
+ if (levels[i].UpHyst != setting->sclk_up_hyst ||
+ levels[i].DownHyst != setting->sclk_down_hyst) {
+ levels[i].UpHyst = setting->sclk_up_hyst;
+ levels[i].DownHyst = setting->sclk_down_hyst;
+ up_hyst_offset = array + (sizeof(SMU74_Discrete_GraphicsLevel) * i)
+ + offsetof(SMU74_Discrete_GraphicsLevel, UpHyst);
+ down_hyst_offset = array + (sizeof(SMU74_Discrete_GraphicsLevel) * i)
+ + offsetof(SMU74_Discrete_GraphicsLevel, DownHyst);
+ offset = up_hyst_offset & ~0x3;
+ tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset));
+ tmp = phm_set_field_to_u32(up_hyst_offset, tmp, levels[i].UpHyst, sizeof(uint8_t));
+ tmp = phm_set_field_to_u32(down_hyst_offset, tmp, levels[i].DownHyst, sizeof(uint8_t));
+ cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp));
+ }
+ }
+ if (!data->sclk_dpm_key_disabled)
+ smum_send_msg_to_smc(hwmgr, PPSMC_MSG_SCLKDPM_UnfreezeLevel);
}
- return smu7_copy_bytes_to_smc(hwmgr, array, (uint8_t *)levels,
- array_size, SMC_RAM_END);
+ if (setting->bupdate_mclk) {
+ if (!data->mclk_dpm_key_disabled)
+ smum_send_msg_to_smc(hwmgr, PPSMC_MSG_MCLKDPM_FreezeLevel);
+ for (i = 0; i < smu_data->smc_state_table.MemoryDpmLevelCount; i++) {
+ if (mclk_levels[i].ActivityLevel !=
+ cpu_to_be16(setting->mclk_activity)) {
+ mclk_levels[i].ActivityLevel = cpu_to_be16(setting->mclk_activity);
+
+ clk_activity_offset = mclk_array + (sizeof(SMU74_Discrete_MemoryLevel) * i)
+ + offsetof(SMU74_Discrete_MemoryLevel, ActivityLevel);
+ offset = clk_activity_offset & ~0x3;
+ tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset));
+ tmp = phm_set_field_to_u32(clk_activity_offset, tmp, mclk_levels[i].ActivityLevel, sizeof(uint16_t));
+ cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp));
+
+ }
+ if (mclk_levels[i].UpHyst != setting->mclk_up_hyst ||
+ mclk_levels[i].DownHyst != setting->mclk_down_hyst) {
+ mclk_levels[i].UpHyst = setting->mclk_up_hyst;
+ mclk_levels[i].DownHyst = setting->mclk_down_hyst;
+ up_hyst_offset = mclk_array + (sizeof(SMU74_Discrete_MemoryLevel) * i)
+ + offsetof(SMU74_Discrete_MemoryLevel, UpHyst);
+ down_hyst_offset = mclk_array + (sizeof(SMU74_Discrete_MemoryLevel) * i)
+ + offsetof(SMU74_Discrete_MemoryLevel, DownHyst);
+ offset = up_hyst_offset & ~0x3;
+ tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset));
+ tmp = phm_set_field_to_u32(up_hyst_offset, tmp, mclk_levels[i].UpHyst, sizeof(uint8_t));
+ tmp = phm_set_field_to_u32(down_hyst_offset, tmp, mclk_levels[i].DownHyst, sizeof(uint8_t));
+ cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp));
+ }
+ }
+ if (!data->mclk_dpm_key_disabled)
+ smum_send_msg_to_smc(hwmgr, PPSMC_MSG_MCLKDPM_UnfreezeLevel);
+ }
+ return 0;
}
const struct pp_smumgr_func polaris10_smu_funcs = {
@@ -2591,6 +2603,6 @@ const struct pp_smumgr_func polaris10_smu_funcs = {
.populate_all_memory_levels = polaris10_populate_all_memory_levels,
.get_mac_definition = polaris10_get_mac_definition,
.is_dpm_running = polaris10_is_dpm_running,
- .populate_requested_graphic_levels = polaris10_populate_requested_graphic_levels,
.is_hw_avfs_present = polaris10_is_hw_avfs_present,
+ .update_dpm_settings = polaris10_update_dpm_settings,
};
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.h b/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.h
index 5e19c24b0561..1ec425df9eda 100644
--- a/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.h
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.h
@@ -59,7 +59,6 @@ struct polaris10_smumgr {
struct SMU74_Discrete_PmFuses power_tune_table;
struct polaris10_range_table range_table[NUM_SCLK_RANGE];
const struct polaris10_pt_defaults *power_tune_defaults;
- uint32_t activity_target[SMU74_MAX_LEVELS_GRAPHICS];
uint32_t bif_sclk_table[SMU74_MAX_LEVELS_LINK];
};
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/rv_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/rv_smumgr.c
deleted file mode 100644
index 2d662b44af54..000000000000
--- a/drivers/gpu/drm/amd/powerplay/smumgr/rv_smumgr.c
+++ /dev/null
@@ -1,406 +0,0 @@
-/*
- * 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 "smumgr.h"
-#include "rv_inc.h"
-#include "pp_soc15.h"
-#include "rv_smumgr.h"
-#include "ppatomctrl.h"
-#include "rv_ppsmc.h"
-#include "smu10_driver_if.h"
-#include "smu10.h"
-#include "ppatomctrl.h"
-#include "pp_debug.h"
-#include "smu_ucode_xfer_vi.h"
-#include "smu7_smumgr.h"
-
-#define VOLTAGE_SCALE 4
-
-#define BUFFER_SIZE 80000
-#define MAX_STRING_SIZE 15
-#define BUFFER_SIZETWO 131072
-
-#define MP0_Public 0x03800000
-#define MP0_SRAM 0x03900000
-#define MP1_Public 0x03b00000
-#define MP1_SRAM 0x03c00004
-
-#define smnMP1_FIRMWARE_FLAGS 0x3010028
-
-
-bool rv_is_smc_ram_running(struct pp_hwmgr *hwmgr)
-{
- uint32_t mp1_fw_flags, reg;
-
- reg = soc15_get_register_offset(NBIF_HWID, 0,
- mmPCIE_INDEX2_BASE_IDX, mmPCIE_INDEX2);
-
- cgs_write_register(hwmgr->device, reg,
- (MP1_Public | (smnMP1_FIRMWARE_FLAGS & 0xffffffff)));
-
- reg = soc15_get_register_offset(NBIF_HWID, 0,
- mmPCIE_DATA2_BASE_IDX, mmPCIE_DATA2);
-
- mp1_fw_flags = cgs_read_register(hwmgr->device, reg);
-
- if (mp1_fw_flags & MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED_MASK)
- return true;
-
- return false;
-}
-
-static uint32_t rv_wait_for_response(struct pp_hwmgr *hwmgr)
-{
- uint32_t reg;
-
- if (!rv_is_smc_ram_running(hwmgr))
- return -EINVAL;
-
- reg = soc15_get_register_offset(MP1_HWID, 0,
- mmMP1_SMN_C2PMSG_90_BASE_IDX, mmMP1_SMN_C2PMSG_90);
-
- phm_wait_for_register_unequal(hwmgr, reg,
- 0, MP1_C2PMSG_90__CONTENT_MASK);
-
- return cgs_read_register(hwmgr->device, reg);
-}
-
-int rv_send_msg_to_smc_without_waiting(struct pp_hwmgr *hwmgr,
- uint16_t msg)
-{
- uint32_t reg;
-
- if (!rv_is_smc_ram_running(hwmgr))
- return -EINVAL;
-
- reg = soc15_get_register_offset(MP1_HWID, 0,
- mmMP1_SMN_C2PMSG_66_BASE_IDX, mmMP1_SMN_C2PMSG_66);
- cgs_write_register(hwmgr->device, reg, msg);
-
- return 0;
-}
-
-int rv_read_arg_from_smc(struct pp_hwmgr *hwmgr, uint32_t *arg)
-{
- uint32_t reg;
-
- reg = soc15_get_register_offset(MP1_HWID, 0,
- mmMP1_SMN_C2PMSG_82_BASE_IDX, mmMP1_SMN_C2PMSG_82);
-
- *arg = cgs_read_register(hwmgr->device, reg);
-
- return 0;
-}
-
-int rv_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg)
-{
- uint32_t reg;
-
- rv_wait_for_response(hwmgr);
-
- reg = soc15_get_register_offset(MP1_HWID, 0,
- mmMP1_SMN_C2PMSG_90_BASE_IDX, mmMP1_SMN_C2PMSG_90);
- cgs_write_register(hwmgr->device, reg, 0);
-
- rv_send_msg_to_smc_without_waiting(hwmgr, msg);
-
- if (rv_wait_for_response(hwmgr) == 0)
- printk("Failed to send Message %x.\n", msg);
-
- return 0;
-}
-
-
-int rv_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr,
- uint16_t msg, uint32_t parameter)
-{
- uint32_t reg;
-
- rv_wait_for_response(hwmgr);
-
- reg = soc15_get_register_offset(MP1_HWID, 0,
- mmMP1_SMN_C2PMSG_90_BASE_IDX, mmMP1_SMN_C2PMSG_90);
- cgs_write_register(hwmgr->device, reg, 0);
-
- reg = soc15_get_register_offset(MP1_HWID, 0,
- mmMP1_SMN_C2PMSG_82_BASE_IDX, mmMP1_SMN_C2PMSG_82);
- cgs_write_register(hwmgr->device, reg, parameter);
-
- rv_send_msg_to_smc_without_waiting(hwmgr, msg);
-
-
- if (rv_wait_for_response(hwmgr) == 0)
- printk("Failed to send Message %x.\n", msg);
-
- return 0;
-}
-
-int rv_copy_table_from_smc(struct pp_hwmgr *hwmgr,
- uint8_t *table, int16_t table_id)
-{
- struct rv_smumgr *priv =
- (struct rv_smumgr *)(hwmgr->smu_backend);
-
- PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE,
- "Invalid SMU Table ID!", return -EINVAL;);
- PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0,
- "Invalid SMU Table version!", return -EINVAL;);
- PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0,
- "Invalid SMU Table Length!", return -EINVAL;);
- PP_ASSERT_WITH_CODE(rv_send_msg_to_smc_with_parameter(hwmgr,
- PPSMC_MSG_SetDriverDramAddrHigh,
- priv->smu_tables.entry[table_id].table_addr_high) == 0,
- "[CopyTableFromSMC] Attempt to Set Dram Addr High Failed!", return -EINVAL;);
- PP_ASSERT_WITH_CODE(rv_send_msg_to_smc_with_parameter(hwmgr,
- PPSMC_MSG_SetDriverDramAddrLow,
- priv->smu_tables.entry[table_id].table_addr_low) == 0,
- "[CopyTableFromSMC] Attempt to Set Dram Addr Low Failed!",
- return -EINVAL;);
- PP_ASSERT_WITH_CODE(rv_send_msg_to_smc_with_parameter(hwmgr,
- PPSMC_MSG_TransferTableSmu2Dram,
- priv->smu_tables.entry[table_id].table_id) == 0,
- "[CopyTableFromSMC] Attempt to Transfer Table From SMU Failed!",
- return -EINVAL;);
-
- memcpy(table, priv->smu_tables.entry[table_id].table,
- priv->smu_tables.entry[table_id].size);
-
- return 0;
-}
-
-int rv_copy_table_to_smc(struct pp_hwmgr *hwmgr,
- uint8_t *table, int16_t table_id)
-{
- struct rv_smumgr *priv =
- (struct rv_smumgr *)(hwmgr->smu_backend);
-
- PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE,
- "Invalid SMU Table ID!", return -EINVAL;);
- PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0,
- "Invalid SMU Table version!", return -EINVAL;);
- PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0,
- "Invalid SMU Table Length!", return -EINVAL;);
-
- memcpy(priv->smu_tables.entry[table_id].table, table,
- priv->smu_tables.entry[table_id].size);
-
- PP_ASSERT_WITH_CODE(rv_send_msg_to_smc_with_parameter(hwmgr,
- PPSMC_MSG_SetDriverDramAddrHigh,
- priv->smu_tables.entry[table_id].table_addr_high) == 0,
- "[CopyTableToSMC] Attempt to Set Dram Addr High Failed!",
- return -EINVAL;);
- PP_ASSERT_WITH_CODE(rv_send_msg_to_smc_with_parameter(hwmgr,
- PPSMC_MSG_SetDriverDramAddrLow,
- priv->smu_tables.entry[table_id].table_addr_low) == 0,
- "[CopyTableToSMC] Attempt to Set Dram Addr Low Failed!",
- return -EINVAL;);
- PP_ASSERT_WITH_CODE(rv_send_msg_to_smc_with_parameter(hwmgr,
- PPSMC_MSG_TransferTableDram2Smu,
- priv->smu_tables.entry[table_id].table_id) == 0,
- "[CopyTableToSMC] Attempt to Transfer Table To SMU Failed!",
- return -EINVAL;);
-
- return 0;
-}
-
-static int rv_verify_smc_interface(struct pp_hwmgr *hwmgr)
-{
- uint32_t smc_driver_if_version;
-
- PP_ASSERT_WITH_CODE(!rv_send_msg_to_smc(hwmgr,
- PPSMC_MSG_GetDriverIfVersion),
- "Attempt to get SMC IF Version Number Failed!",
- return -EINVAL);
- PP_ASSERT_WITH_CODE(!rv_read_arg_from_smc(hwmgr,
- &smc_driver_if_version),
- "Attempt to read SMC IF Version Number Failed!",
- return -EINVAL);
-
- if (smc_driver_if_version != SMU10_DRIVER_IF_VERSION)
- return -EINVAL;
-
- return 0;
-}
-
-/* sdma is disabled by default in vbios, need to re-enable in driver */
-static int rv_smc_enable_sdma(struct pp_hwmgr *hwmgr)
-{
- PP_ASSERT_WITH_CODE(!rv_send_msg_to_smc(hwmgr,
- PPSMC_MSG_PowerUpSdma),
- "Attempt to power up sdma Failed!",
- return -EINVAL);
-
- return 0;
-}
-
-static int rv_smc_disable_sdma(struct pp_hwmgr *hwmgr)
-{
- PP_ASSERT_WITH_CODE(!rv_send_msg_to_smc(hwmgr,
- PPSMC_MSG_PowerDownSdma),
- "Attempt to power down sdma Failed!",
- return -EINVAL);
-
- return 0;
-}
-
-/* vcn is disabled by default in vbios, need to re-enable in driver */
-static int rv_smc_enable_vcn(struct pp_hwmgr *hwmgr)
-{
- PP_ASSERT_WITH_CODE(!rv_send_msg_to_smc_with_parameter(hwmgr,
- PPSMC_MSG_PowerUpVcn, 0),
- "Attempt to power up vcn Failed!",
- return -EINVAL);
-
- return 0;
-}
-
-static int rv_smc_disable_vcn(struct pp_hwmgr *hwmgr)
-{
- PP_ASSERT_WITH_CODE(!rv_send_msg_to_smc_with_parameter(hwmgr,
- PPSMC_MSG_PowerDownVcn, 0),
- "Attempt to power down vcn Failed!",
- return -EINVAL);
-
- return 0;
-}
-
-static int rv_smu_fini(struct pp_hwmgr *hwmgr)
-{
- struct rv_smumgr *priv =
- (struct rv_smumgr *)(hwmgr->smu_backend);
-
- if (priv) {
- rv_smc_disable_sdma(hwmgr);
- rv_smc_disable_vcn(hwmgr);
- cgs_free_gpu_mem(hwmgr->device,
- priv->smu_tables.entry[WMTABLE].handle);
- cgs_free_gpu_mem(hwmgr->device,
- priv->smu_tables.entry[CLOCKTABLE].handle);
- kfree(hwmgr->smu_backend);
- hwmgr->smu_backend = NULL;
- }
-
- return 0;
-}
-
-static int rv_start_smu(struct pp_hwmgr *hwmgr)
-{
- struct cgs_firmware_info info = {0};
-
- smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetSmuVersion);
- rv_read_arg_from_smc(hwmgr, &hwmgr->smu_version);
- info.version = hwmgr->smu_version >> 8;
-
- cgs_get_firmware_info(hwmgr->device, CGS_UCODE_ID_SMU, &info);
-
- if (rv_verify_smc_interface(hwmgr))
- return -EINVAL;
- if (rv_smc_enable_sdma(hwmgr))
- return -EINVAL;
- if (rv_smc_enable_vcn(hwmgr))
- return -EINVAL;
-
- return 0;
-}
-
-static int rv_smu_init(struct pp_hwmgr *hwmgr)
-{
- struct rv_smumgr *priv;
- uint64_t mc_addr;
- void *kaddr = NULL;
- unsigned long handle;
-
- priv = kzalloc(sizeof(struct rv_smumgr), GFP_KERNEL);
-
- if (!priv)
- return -ENOMEM;
-
- hwmgr->smu_backend = priv;
-
- /* allocate space for watermarks table */
- smu_allocate_memory(hwmgr->device,
- sizeof(Watermarks_t),
- CGS_GPU_MEM_TYPE__GART_CACHEABLE,
- PAGE_SIZE,
- &mc_addr,
- &kaddr,
- &handle);
-
- PP_ASSERT_WITH_CODE(kaddr,
- "[rv_smu_init] Out of memory for wmtable.",
- kfree(hwmgr->smu_backend);
- hwmgr->smu_backend = NULL;
- return -EINVAL);
-
- priv->smu_tables.entry[WMTABLE].version = 0x01;
- priv->smu_tables.entry[WMTABLE].size = sizeof(Watermarks_t);
- priv->smu_tables.entry[WMTABLE].table_id = TABLE_WATERMARKS;
- priv->smu_tables.entry[WMTABLE].table_addr_high =
- smu_upper_32_bits(mc_addr);
- priv->smu_tables.entry[WMTABLE].table_addr_low =
- smu_lower_32_bits(mc_addr);
- priv->smu_tables.entry[WMTABLE].table = kaddr;
- priv->smu_tables.entry[WMTABLE].handle = handle;
-
- /* allocate space for watermarks table */
- smu_allocate_memory(hwmgr->device,
- sizeof(DpmClocks_t),
- CGS_GPU_MEM_TYPE__GART_CACHEABLE,
- PAGE_SIZE,
- &mc_addr,
- &kaddr,
- &handle);
-
- PP_ASSERT_WITH_CODE(kaddr,
- "[rv_smu_init] Out of memory for CLOCKTABLE.",
- cgs_free_gpu_mem(hwmgr->device,
- (cgs_handle_t)priv->smu_tables.entry[WMTABLE].handle);
- kfree(hwmgr->smu_backend);
- hwmgr->smu_backend = NULL;
- return -EINVAL);
-
- priv->smu_tables.entry[CLOCKTABLE].version = 0x01;
- priv->smu_tables.entry[CLOCKTABLE].size = sizeof(DpmClocks_t);
- priv->smu_tables.entry[CLOCKTABLE].table_id = TABLE_DPMCLOCKS;
- priv->smu_tables.entry[CLOCKTABLE].table_addr_high =
- smu_upper_32_bits(mc_addr);
- priv->smu_tables.entry[CLOCKTABLE].table_addr_low =
- smu_lower_32_bits(mc_addr);
- priv->smu_tables.entry[CLOCKTABLE].table = kaddr;
- priv->smu_tables.entry[CLOCKTABLE].handle = handle;
-
- return 0;
-}
-
-const struct pp_smumgr_func rv_smu_funcs = {
- .smu_init = &rv_smu_init,
- .smu_fini = &rv_smu_fini,
- .start_smu = &rv_start_smu,
- .request_smu_load_specific_fw = NULL,
- .send_msg_to_smc = &rv_send_msg_to_smc,
- .send_msg_to_smc_with_parameter = &rv_send_msg_to_smc_with_parameter,
- .download_pptable_settings = NULL,
- .upload_pptable_settings = NULL,
-};
-
-
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smu10_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/smu10_smumgr.c
new file mode 100644
index 000000000000..bc53f2beda30
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/smu10_smumgr.c
@@ -0,0 +1,344 @@
+/*
+ * 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 "smumgr.h"
+#include "smu10_inc.h"
+#include "pp_soc15.h"
+#include "smu10_smumgr.h"
+#include "ppatomctrl.h"
+#include "rv_ppsmc.h"
+#include "smu10_driver_if.h"
+#include "smu10.h"
+#include "ppatomctrl.h"
+#include "pp_debug.h"
+
+
+#define VOLTAGE_SCALE 4
+
+#define BUFFER_SIZE 80000
+#define MAX_STRING_SIZE 15
+#define BUFFER_SIZETWO 131072
+
+#define MP0_Public 0x03800000
+#define MP0_SRAM 0x03900000
+#define MP1_Public 0x03b00000
+#define MP1_SRAM 0x03c00004
+
+#define smnMP1_FIRMWARE_FLAGS 0x3010028
+
+
+static uint32_t smu10_wait_for_response(struct pp_hwmgr *hwmgr)
+{
+ uint32_t reg;
+
+ reg = soc15_get_register_offset(MP1_HWID, 0,
+ mmMP1_SMN_C2PMSG_90_BASE_IDX, mmMP1_SMN_C2PMSG_90);
+
+ phm_wait_for_register_unequal(hwmgr, reg,
+ 0, MP1_C2PMSG_90__CONTENT_MASK);
+
+ return cgs_read_register(hwmgr->device, reg);
+}
+
+static int smu10_send_msg_to_smc_without_waiting(struct pp_hwmgr *hwmgr,
+ uint16_t msg)
+{
+ uint32_t reg;
+
+ reg = soc15_get_register_offset(MP1_HWID, 0,
+ mmMP1_SMN_C2PMSG_66_BASE_IDX, mmMP1_SMN_C2PMSG_66);
+ cgs_write_register(hwmgr->device, reg, msg);
+
+ return 0;
+}
+
+static int smu10_read_arg_from_smc(struct pp_hwmgr *hwmgr)
+{
+ uint32_t reg;
+
+ reg = soc15_get_register_offset(MP1_HWID, 0,
+ mmMP1_SMN_C2PMSG_82_BASE_IDX, mmMP1_SMN_C2PMSG_82);
+
+ return cgs_read_register(hwmgr->device, reg);
+}
+
+static int smu10_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg)
+{
+ uint32_t reg;
+
+ smu10_wait_for_response(hwmgr);
+
+ reg = soc15_get_register_offset(MP1_HWID, 0,
+ mmMP1_SMN_C2PMSG_90_BASE_IDX, mmMP1_SMN_C2PMSG_90);
+ cgs_write_register(hwmgr->device, reg, 0);
+
+ smu10_send_msg_to_smc_without_waiting(hwmgr, msg);
+
+ if (smu10_wait_for_response(hwmgr) == 0)
+ printk("Failed to send Message %x.\n", msg);
+
+ return 0;
+}
+
+
+static int smu10_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr,
+ uint16_t msg, uint32_t parameter)
+{
+ uint32_t reg;
+
+ smu10_wait_for_response(hwmgr);
+
+ reg = soc15_get_register_offset(MP1_HWID, 0,
+ mmMP1_SMN_C2PMSG_90_BASE_IDX, mmMP1_SMN_C2PMSG_90);
+ cgs_write_register(hwmgr->device, reg, 0);
+
+ reg = soc15_get_register_offset(MP1_HWID, 0,
+ mmMP1_SMN_C2PMSG_82_BASE_IDX, mmMP1_SMN_C2PMSG_82);
+ cgs_write_register(hwmgr->device, reg, parameter);
+
+ smu10_send_msg_to_smc_without_waiting(hwmgr, msg);
+
+
+ if (smu10_wait_for_response(hwmgr) == 0)
+ printk("Failed to send Message %x.\n", msg);
+
+ return 0;
+}
+
+static int smu10_copy_table_from_smc(struct pp_hwmgr *hwmgr,
+ uint8_t *table, int16_t table_id)
+{
+ struct smu10_smumgr *priv =
+ (struct smu10_smumgr *)(hwmgr->smu_backend);
+
+ PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE,
+ "Invalid SMU Table ID!", return -EINVAL;);
+ PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0,
+ "Invalid SMU Table version!", return -EINVAL;);
+ PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0,
+ "Invalid SMU Table Length!", return -EINVAL;);
+ smu10_send_msg_to_smc_with_parameter(hwmgr,
+ PPSMC_MSG_SetDriverDramAddrHigh,
+ upper_32_bits(priv->smu_tables.entry[table_id].mc_addr));
+ smu10_send_msg_to_smc_with_parameter(hwmgr,
+ PPSMC_MSG_SetDriverDramAddrLow,
+ lower_32_bits(priv->smu_tables.entry[table_id].mc_addr));
+ smu10_send_msg_to_smc_with_parameter(hwmgr,
+ PPSMC_MSG_TransferTableSmu2Dram,
+ priv->smu_tables.entry[table_id].table_id);
+
+ memcpy(table, (uint8_t *)priv->smu_tables.entry[table_id].table,
+ priv->smu_tables.entry[table_id].size);
+
+ return 0;
+}
+
+static int smu10_copy_table_to_smc(struct pp_hwmgr *hwmgr,
+ uint8_t *table, int16_t table_id)
+{
+ struct smu10_smumgr *priv =
+ (struct smu10_smumgr *)(hwmgr->smu_backend);
+
+ PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE,
+ "Invalid SMU Table ID!", return -EINVAL;);
+ PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0,
+ "Invalid SMU Table version!", return -EINVAL;);
+ PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0,
+ "Invalid SMU Table Length!", return -EINVAL;);
+
+ memcpy(priv->smu_tables.entry[table_id].table, table,
+ priv->smu_tables.entry[table_id].size);
+
+ smu10_send_msg_to_smc_with_parameter(hwmgr,
+ PPSMC_MSG_SetDriverDramAddrHigh,
+ upper_32_bits(priv->smu_tables.entry[table_id].mc_addr));
+ smu10_send_msg_to_smc_with_parameter(hwmgr,
+ PPSMC_MSG_SetDriverDramAddrLow,
+ lower_32_bits(priv->smu_tables.entry[table_id].mc_addr));
+ smu10_send_msg_to_smc_with_parameter(hwmgr,
+ PPSMC_MSG_TransferTableDram2Smu,
+ priv->smu_tables.entry[table_id].table_id);
+
+ return 0;
+}
+
+static int smu10_verify_smc_interface(struct pp_hwmgr *hwmgr)
+{
+ uint32_t smc_driver_if_version;
+
+ smu10_send_msg_to_smc(hwmgr,
+ PPSMC_MSG_GetDriverIfVersion);
+ smc_driver_if_version = smu10_read_arg_from_smc(hwmgr);
+
+ if (smc_driver_if_version != SMU10_DRIVER_IF_VERSION) {
+ pr_err("Attempt to read SMC IF Version Number Failed!\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/* sdma is disabled by default in vbios, need to re-enable in driver */
+static void smu10_smc_enable_sdma(struct pp_hwmgr *hwmgr)
+{
+ smu10_send_msg_to_smc(hwmgr,
+ PPSMC_MSG_PowerUpSdma);
+}
+
+static void smu10_smc_disable_sdma(struct pp_hwmgr *hwmgr)
+{
+ smu10_send_msg_to_smc(hwmgr,
+ PPSMC_MSG_PowerDownSdma);
+}
+
+/* vcn is disabled by default in vbios, need to re-enable in driver */
+static void smu10_smc_enable_vcn(struct pp_hwmgr *hwmgr)
+{
+ smu10_send_msg_to_smc_with_parameter(hwmgr,
+ PPSMC_MSG_PowerUpVcn, 0);
+}
+
+static void smu10_smc_disable_vcn(struct pp_hwmgr *hwmgr)
+{
+ smu10_send_msg_to_smc_with_parameter(hwmgr,
+ PPSMC_MSG_PowerDownVcn, 0);
+}
+
+static int smu10_smu_fini(struct pp_hwmgr *hwmgr)
+{
+ struct smu10_smumgr *priv =
+ (struct smu10_smumgr *)(hwmgr->smu_backend);
+
+ if (priv) {
+ smu10_smc_disable_sdma(hwmgr);
+ smu10_smc_disable_vcn(hwmgr);
+ amdgpu_bo_free_kernel(&priv->smu_tables.entry[SMU10_WMTABLE].handle,
+ &priv->smu_tables.entry[SMU10_WMTABLE].mc_addr,
+ &priv->smu_tables.entry[SMU10_WMTABLE].table);
+ amdgpu_bo_free_kernel(&priv->smu_tables.entry[SMU10_CLOCKTABLE].handle,
+ &priv->smu_tables.entry[SMU10_CLOCKTABLE].mc_addr,
+ &priv->smu_tables.entry[SMU10_CLOCKTABLE].table);
+ kfree(hwmgr->smu_backend);
+ hwmgr->smu_backend = NULL;
+ }
+
+ return 0;
+}
+
+static int smu10_start_smu(struct pp_hwmgr *hwmgr)
+{
+ struct amdgpu_device *adev = hwmgr->adev;
+
+ smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetSmuVersion);
+ hwmgr->smu_version = smu10_read_arg_from_smc(hwmgr);
+ adev->pm.fw_version = hwmgr->smu_version >> 8;
+
+ if (smu10_verify_smc_interface(hwmgr))
+ return -EINVAL;
+ smu10_smc_enable_sdma(hwmgr);
+ smu10_smc_enable_vcn(hwmgr);
+ return 0;
+}
+
+static int smu10_smu_init(struct pp_hwmgr *hwmgr)
+{
+ struct smu10_smumgr *priv;
+ int r;
+
+ priv = kzalloc(sizeof(struct smu10_smumgr), GFP_KERNEL);
+
+ if (!priv)
+ return -ENOMEM;
+
+ hwmgr->smu_backend = priv;
+
+ /* allocate space for watermarks table */
+ r = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
+ sizeof(Watermarks_t),
+ PAGE_SIZE,
+ AMDGPU_GEM_DOMAIN_VRAM,
+ &priv->smu_tables.entry[SMU10_WMTABLE].handle,
+ &priv->smu_tables.entry[SMU10_WMTABLE].mc_addr,
+ &priv->smu_tables.entry[SMU10_WMTABLE].table);
+
+ if (r)
+ goto err0;
+
+ priv->smu_tables.entry[SMU10_WMTABLE].version = 0x01;
+ priv->smu_tables.entry[SMU10_WMTABLE].size = sizeof(Watermarks_t);
+ priv->smu_tables.entry[SMU10_WMTABLE].table_id = TABLE_WATERMARKS;
+
+ /* allocate space for watermarks table */
+ r = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
+ sizeof(DpmClocks_t),
+ PAGE_SIZE,
+ AMDGPU_GEM_DOMAIN_VRAM,
+ &priv->smu_tables.entry[SMU10_CLOCKTABLE].handle,
+ &priv->smu_tables.entry[SMU10_CLOCKTABLE].mc_addr,
+ &priv->smu_tables.entry[SMU10_CLOCKTABLE].table);
+
+ if (r)
+ goto err1;
+
+ priv->smu_tables.entry[SMU10_CLOCKTABLE].version = 0x01;
+ priv->smu_tables.entry[SMU10_CLOCKTABLE].size = sizeof(DpmClocks_t);
+ priv->smu_tables.entry[SMU10_CLOCKTABLE].table_id = TABLE_DPMCLOCKS;
+
+ return 0;
+
+err1:
+ amdgpu_bo_free_kernel(&priv->smu_tables.entry[SMU10_WMTABLE].handle,
+ &priv->smu_tables.entry[SMU10_WMTABLE].mc_addr,
+ &priv->smu_tables.entry[SMU10_WMTABLE].table);
+err0:
+ kfree(priv);
+ return -EINVAL;
+}
+
+static int smu10_smc_table_manager(struct pp_hwmgr *hwmgr, uint8_t *table, uint16_t table_id, bool rw)
+{
+ int ret;
+
+ if (rw)
+ ret = smu10_copy_table_from_smc(hwmgr, table, table_id);
+ else
+ ret = smu10_copy_table_to_smc(hwmgr, table, table_id);
+
+ return ret;
+}
+
+
+const struct pp_smumgr_func smu10_smu_funcs = {
+ .smu_init = &smu10_smu_init,
+ .smu_fini = &smu10_smu_fini,
+ .start_smu = &smu10_start_smu,
+ .request_smu_load_specific_fw = NULL,
+ .send_msg_to_smc = &smu10_send_msg_to_smc,
+ .send_msg_to_smc_with_parameter = &smu10_send_msg_to_smc_with_parameter,
+ .download_pptable_settings = NULL,
+ .upload_pptable_settings = NULL,
+ .get_argument = smu10_read_arg_from_smc,
+ .smc_table_manager = smu10_smc_table_manager,
+};
+
+
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/rv_smumgr.h b/drivers/gpu/drm/amd/powerplay/smumgr/smu10_smumgr.h
index caebdbebdcd8..9c2be74a2b2f 100644
--- a/drivers/gpu/drm/amd/powerplay/smumgr/rv_smumgr.h
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/smu10_smumgr.h
@@ -21,42 +21,30 @@
*
*/
-#ifndef PP_RAVEN_SMUMANAGER_H
-#define PP_RAVEN_SMUMANAGER_H
+#ifndef PP_SMU10_SMUMANAGER_H
+#define PP_SMU10_SMUMANAGER_H
#include "rv_ppsmc.h"
#include "smu10_driver_if.h"
-enum SMU_TABLE_ID {
- WMTABLE = 0,
- CLOCKTABLE,
- MAX_SMU_TABLE,
-};
+#define MAX_SMU_TABLE 2
struct smu_table_entry {
uint32_t version;
uint32_t size;
uint32_t table_id;
- uint32_t table_addr_high;
- uint32_t table_addr_low;
- uint8_t *table;
- unsigned long handle;
+ uint64_t mc_addr;
+ void *table;
+ struct amdgpu_bo *handle;
};
struct smu_table_array {
struct smu_table_entry entry[MAX_SMU_TABLE];
};
-struct rv_smumgr {
+struct smu10_smumgr {
struct smu_table_array smu_tables;
};
-int rv_read_arg_from_smc(struct pp_hwmgr *hwmgr, uint32_t *arg);
-bool rv_is_smc_ram_running(struct pp_hwmgr *hwmgr);
-int rv_copy_table_from_smc(struct pp_hwmgr *hwmgr,
- uint8_t *table, int16_t table_id);
-int rv_copy_table_to_smc(struct pp_hwmgr *hwmgr,
- uint8_t *table, int16_t table_id);
-
#endif
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.c
index 311ff3718618..0399c10d2be0 100644
--- a/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.c
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.c
@@ -369,8 +369,8 @@ static int smu7_populate_single_firmware_entry(struct pp_hwmgr *hwmgr,
if (!result) {
entry->version = info.fw_version;
entry->id = (uint16_t)fw_type;
- entry->image_addr_high = smu_upper_32_bits(info.mc_addr);
- entry->image_addr_low = smu_lower_32_bits(info.mc_addr);
+ entry->image_addr_high = upper_32_bits(info.mc_addr);
+ entry->image_addr_low = lower_32_bits(info.mc_addr);
entry->meta_data_addr_high = 0;
entry->meta_data_addr_low = 0;
@@ -412,10 +412,10 @@ int smu7_request_smu_load_fw(struct pp_hwmgr *hwmgr)
if (!cgs_is_virtualization_enabled(hwmgr->device)) {
smu7_send_msg_to_smc_with_parameter(hwmgr,
PPSMC_MSG_SMU_DRAM_ADDR_HI,
- smu_data->smu_buffer.mc_addr_high);
+ upper_32_bits(smu_data->smu_buffer.mc_addr));
smu7_send_msg_to_smc_with_parameter(hwmgr,
PPSMC_MSG_SMU_DRAM_ADDR_LO,
- smu_data->smu_buffer.mc_addr_low);
+ lower_32_bits(smu_data->smu_buffer.mc_addr));
}
fw_to_load = UCODE_ID_RLC_G_MASK
+ UCODE_ID_SDMA0_MASK
@@ -472,8 +472,8 @@ int smu7_request_smu_load_fw(struct pp_hwmgr *hwmgr)
UCODE_ID_MEC_STORAGE, &toc->entry[toc->num_entries++]),
"Failed to Get Firmware Entry.", return -EINVAL);
- smu7_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_DRV_DRAM_ADDR_HI, smu_data->header_buffer.mc_addr_high);
- smu7_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_DRV_DRAM_ADDR_LO, smu_data->header_buffer.mc_addr_low);
+ smu7_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_DRV_DRAM_ADDR_HI, upper_32_bits(smu_data->header_buffer.mc_addr));
+ smu7_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_DRV_DRAM_ADDR_LO, lower_32_bits(smu_data->header_buffer.mc_addr));
if (smu7_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_LoadUcodes, fw_to_load))
pr_err("Fail to Request SMU Load uCode");
@@ -585,9 +585,8 @@ int smu7_setup_pwr_virus(struct pp_hwmgr *hwmgr)
int smu7_init(struct pp_hwmgr *hwmgr)
{
struct smu7_smumgr *smu_data;
- uint8_t *internal_buf;
uint64_t mc_addr = 0;
-
+ int r;
/* Allocate memory for backend private data */
smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend);
smu_data->header_buffer.data_size =
@@ -595,52 +594,42 @@ int smu7_init(struct pp_hwmgr *hwmgr)
/* Allocate FW image data structure and header buffer and
* send the header buffer address to SMU */
- smu_allocate_memory(hwmgr->device,
+ r = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
smu_data->header_buffer.data_size,
- CGS_GPU_MEM_TYPE__VISIBLE_CONTIG_FB,
PAGE_SIZE,
+ AMDGPU_GEM_DOMAIN_VRAM,
+ &smu_data->header_buffer.handle,
&mc_addr,
- &smu_data->header_buffer.kaddr,
- &smu_data->header_buffer.handle);
+ &smu_data->header_buffer.kaddr);
- smu_data->header = smu_data->header_buffer.kaddr;
- smu_data->header_buffer.mc_addr_high = smu_upper_32_bits(mc_addr);
- smu_data->header_buffer.mc_addr_low = smu_lower_32_bits(mc_addr);
+ if (r)
+ return -EINVAL;
- PP_ASSERT_WITH_CODE((NULL != smu_data->header),
- "Out of memory.",
- kfree(hwmgr->smu_backend);
- cgs_free_gpu_mem(hwmgr->device,
- (cgs_handle_t)smu_data->header_buffer.handle);
- return -EINVAL);
+ smu_data->header = smu_data->header_buffer.kaddr;
+ smu_data->header_buffer.mc_addr = mc_addr;
if (cgs_is_virtualization_enabled(hwmgr->device))
return 0;
smu_data->smu_buffer.data_size = 200*4096;
- smu_allocate_memory(hwmgr->device,
+ r = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
smu_data->smu_buffer.data_size,
- CGS_GPU_MEM_TYPE__VISIBLE_CONTIG_FB,
PAGE_SIZE,
+ AMDGPU_GEM_DOMAIN_VRAM,
+ &smu_data->smu_buffer.handle,
&mc_addr,
- &smu_data->smu_buffer.kaddr,
- &smu_data->smu_buffer.handle);
-
- internal_buf = smu_data->smu_buffer.kaddr;
- smu_data->smu_buffer.mc_addr_high = smu_upper_32_bits(mc_addr);
- smu_data->smu_buffer.mc_addr_low = smu_lower_32_bits(mc_addr);
+ &smu_data->smu_buffer.kaddr);
- PP_ASSERT_WITH_CODE((NULL != internal_buf),
- "Out of memory.",
- kfree(hwmgr->smu_backend);
- cgs_free_gpu_mem(hwmgr->device,
- (cgs_handle_t)smu_data->smu_buffer.handle);
- return -EINVAL);
+ if (r) {
+ amdgpu_bo_free_kernel(&smu_data->header_buffer.handle,
+ &smu_data->header_buffer.mc_addr,
+ &smu_data->header_buffer.kaddr);
+ return -EINVAL;
+ }
+ smu_data->smu_buffer.mc_addr = mc_addr;
if (smum_is_hw_avfs_present(hwmgr))
- smu_data->avfs.avfs_btc_status = AVFS_BTC_BOOT;
- else
- smu_data->avfs.avfs_btc_status = AVFS_BTC_NOTSUPPORTED;
+ hwmgr->avfs_supported = true;
return 0;
}
@@ -650,9 +639,14 @@ int smu7_smu_fini(struct pp_hwmgr *hwmgr)
{
struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend);
- smu_free_memory(hwmgr->device, (void *) smu_data->header_buffer.handle);
+ amdgpu_bo_free_kernel(&smu_data->header_buffer.handle,
+ &smu_data->header_buffer.mc_addr,
+ &smu_data->header_buffer.kaddr);
+
if (!cgs_is_virtualization_enabled(hwmgr->device))
- smu_free_memory(hwmgr->device, (void *) smu_data->smu_buffer.handle);
+ amdgpu_bo_free_kernel(&smu_data->smu_buffer.handle,
+ &smu_data->smu_buffer.mc_addr,
+ &smu_data->smu_buffer.kaddr);
kfree(hwmgr->smu_backend);
hwmgr->smu_backend = NULL;
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.h b/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.h
index c87263bc0caa..126d300259ba 100644
--- a/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.h
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.h
@@ -31,15 +31,9 @@
struct smu7_buffer_entry {
uint32_t data_size;
- uint32_t mc_addr_low;
- uint32_t mc_addr_high;
+ uint64_t mc_addr;
void *kaddr;
- unsigned long handle;
-};
-
-struct smu7_avfs {
- enum AVFS_BTC_STATUS avfs_btc_status;
- uint32_t avfs_btc_param;
+ struct amdgpu_bo *handle;
};
struct smu7_smumgr {
@@ -56,7 +50,7 @@ struct smu7_smumgr {
uint32_t ulv_setting_starts;
uint8_t security_hard_key;
uint32_t acpi_optimization;
- struct smu7_avfs avfs;
+ uint32_t avfs_btc_param;
};
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c
new file mode 100644
index 000000000000..c861d3023474
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c
@@ -0,0 +1,891 @@
+/*
+ * 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/delay.h>
+#include <linux/gfp.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#include "cgs_common.h"
+#include "smu/smu_8_0_d.h"
+#include "smu/smu_8_0_sh_mask.h"
+#include "smu8.h"
+#include "smu8_fusion.h"
+#include "smu8_smumgr.h"
+#include "cz_ppsmc.h"
+#include "smu_ucode_xfer_cz.h"
+#include "gca/gfx_8_0_d.h"
+#include "gca/gfx_8_0_sh_mask.h"
+#include "smumgr.h"
+
+#define SIZE_ALIGN_32(x) (((x) + 31) / 32 * 32)
+
+static const enum smu8_scratch_entry firmware_list[] = {
+ SMU8_SCRATCH_ENTRY_UCODE_ID_SDMA0,
+ SMU8_SCRATCH_ENTRY_UCODE_ID_SDMA1,
+ SMU8_SCRATCH_ENTRY_UCODE_ID_CP_CE,
+ SMU8_SCRATCH_ENTRY_UCODE_ID_CP_PFP,
+ SMU8_SCRATCH_ENTRY_UCODE_ID_CP_ME,
+ SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1,
+ SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2,
+ SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_G,
+};
+
+static int smu8_get_argument(struct pp_hwmgr *hwmgr)
+{
+ if (hwmgr == NULL || hwmgr->device == NULL)
+ return -EINVAL;
+
+ return cgs_read_register(hwmgr->device,
+ mmSMU_MP1_SRBM2P_ARG_0);
+}
+
+static int smu8_send_msg_to_smc_async(struct pp_hwmgr *hwmgr, uint16_t msg)
+{
+ int result = 0;
+
+ if (hwmgr == NULL || hwmgr->device == NULL)
+ return -EINVAL;
+
+ result = PHM_WAIT_FIELD_UNEQUAL(hwmgr,
+ SMU_MP1_SRBM2P_RESP_0, CONTENT, 0);
+ if (result != 0) {
+ pr_err("smu8_send_msg_to_smc_async (0x%04x) failed\n", msg);
+ return result;
+ }
+
+ cgs_write_register(hwmgr->device, mmSMU_MP1_SRBM2P_RESP_0, 0);
+ cgs_write_register(hwmgr->device, mmSMU_MP1_SRBM2P_MSG_0, msg);
+
+ return 0;
+}
+
+/* Send a message to the SMC, and wait for its response.*/
+static int smu8_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg)
+{
+ int result = 0;
+
+ result = smu8_send_msg_to_smc_async(hwmgr, msg);
+ if (result != 0)
+ return result;
+
+ return PHM_WAIT_FIELD_UNEQUAL(hwmgr,
+ SMU_MP1_SRBM2P_RESP_0, CONTENT, 0);
+}
+
+static int smu8_set_smc_sram_address(struct pp_hwmgr *hwmgr,
+ uint32_t smc_address, uint32_t limit)
+{
+ if (hwmgr == NULL || hwmgr->device == NULL)
+ return -EINVAL;
+
+ if (0 != (3 & smc_address)) {
+ pr_err("SMC address must be 4 byte aligned\n");
+ return -EINVAL;
+ }
+
+ if (limit <= (smc_address + 3)) {
+ pr_err("SMC address beyond the SMC RAM area\n");
+ return -EINVAL;
+ }
+
+ cgs_write_register(hwmgr->device, mmMP0PUB_IND_INDEX_0,
+ SMN_MP1_SRAM_START_ADDR + smc_address);
+
+ return 0;
+}
+
+static int smu8_write_smc_sram_dword(struct pp_hwmgr *hwmgr,
+ uint32_t smc_address, uint32_t value, uint32_t limit)
+{
+ int result;
+
+ if (hwmgr == NULL || hwmgr->device == NULL)
+ return -EINVAL;
+
+ result = smu8_set_smc_sram_address(hwmgr, smc_address, limit);
+ if (!result)
+ cgs_write_register(hwmgr->device, mmMP0PUB_IND_DATA_0, value);
+
+ return result;
+}
+
+static int smu8_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr,
+ uint16_t msg, uint32_t parameter)
+{
+ if (hwmgr == NULL || hwmgr->device == NULL)
+ return -EINVAL;
+
+ cgs_write_register(hwmgr->device, mmSMU_MP1_SRBM2P_ARG_0, parameter);
+
+ return smu8_send_msg_to_smc(hwmgr, msg);
+}
+
+static int smu8_check_fw_load_finish(struct pp_hwmgr *hwmgr,
+ uint32_t firmware)
+{
+ int i;
+ uint32_t index = SMN_MP1_SRAM_START_ADDR +
+ SMU8_FIRMWARE_HEADER_LOCATION +
+ offsetof(struct SMU8_Firmware_Header, UcodeLoadStatus);
+
+ if (hwmgr == NULL || hwmgr->device == NULL)
+ return -EINVAL;
+
+ cgs_write_register(hwmgr->device, mmMP0PUB_IND_INDEX, index);
+
+ for (i = 0; i < hwmgr->usec_timeout; i++) {
+ if (firmware ==
+ (cgs_read_register(hwmgr->device, mmMP0PUB_IND_DATA) & firmware))
+ break;
+ udelay(1);
+ }
+
+ if (i >= hwmgr->usec_timeout) {
+ pr_err("SMU check loaded firmware failed.\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int smu8_load_mec_firmware(struct pp_hwmgr *hwmgr)
+{
+ uint32_t reg_data;
+ uint32_t tmp;
+ int ret = 0;
+ struct cgs_firmware_info info = {0};
+ struct smu8_smumgr *smu8_smu;
+
+ if (hwmgr == NULL || hwmgr->device == NULL)
+ return -EINVAL;
+
+ smu8_smu = hwmgr->smu_backend;
+ ret = cgs_get_firmware_info(hwmgr->device,
+ CGS_UCODE_ID_CP_MEC, &info);
+
+ if (ret)
+ return -EINVAL;
+
+ /* Disable MEC parsing/prefetching */
+ tmp = cgs_read_register(hwmgr->device,
+ mmCP_MEC_CNTL);
+ tmp = PHM_SET_FIELD(tmp, CP_MEC_CNTL, MEC_ME1_HALT, 1);
+ tmp = PHM_SET_FIELD(tmp, CP_MEC_CNTL, MEC_ME2_HALT, 1);
+ cgs_write_register(hwmgr->device, mmCP_MEC_CNTL, tmp);
+
+ tmp = cgs_read_register(hwmgr->device,
+ mmCP_CPC_IC_BASE_CNTL);
+
+ tmp = PHM_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, VMID, 0);
+ tmp = PHM_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, ATC, 0);
+ tmp = PHM_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, CACHE_POLICY, 0);
+ tmp = PHM_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, MTYPE, 1);
+ cgs_write_register(hwmgr->device, mmCP_CPC_IC_BASE_CNTL, tmp);
+
+ reg_data = lower_32_bits(info.mc_addr) &
+ PHM_FIELD_MASK(CP_CPC_IC_BASE_LO, IC_BASE_LO);
+ cgs_write_register(hwmgr->device, mmCP_CPC_IC_BASE_LO, reg_data);
+
+ reg_data = upper_32_bits(info.mc_addr) &
+ PHM_FIELD_MASK(CP_CPC_IC_BASE_HI, IC_BASE_HI);
+ cgs_write_register(hwmgr->device, mmCP_CPC_IC_BASE_HI, reg_data);
+
+ return 0;
+}
+
+static uint8_t smu8_translate_firmware_enum_to_arg(struct pp_hwmgr *hwmgr,
+ enum smu8_scratch_entry firmware_enum)
+{
+ uint8_t ret = 0;
+
+ switch (firmware_enum) {
+ case SMU8_SCRATCH_ENTRY_UCODE_ID_SDMA0:
+ ret = UCODE_ID_SDMA0;
+ break;
+ case SMU8_SCRATCH_ENTRY_UCODE_ID_SDMA1:
+ if (hwmgr->chip_id == CHIP_STONEY)
+ ret = UCODE_ID_SDMA0;
+ else
+ ret = UCODE_ID_SDMA1;
+ break;
+ case SMU8_SCRATCH_ENTRY_UCODE_ID_CP_CE:
+ ret = UCODE_ID_CP_CE;
+ break;
+ case SMU8_SCRATCH_ENTRY_UCODE_ID_CP_PFP:
+ ret = UCODE_ID_CP_PFP;
+ break;
+ case SMU8_SCRATCH_ENTRY_UCODE_ID_CP_ME:
+ ret = UCODE_ID_CP_ME;
+ break;
+ case SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1:
+ ret = UCODE_ID_CP_MEC_JT1;
+ break;
+ case SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2:
+ if (hwmgr->chip_id == CHIP_STONEY)
+ ret = UCODE_ID_CP_MEC_JT1;
+ else
+ ret = UCODE_ID_CP_MEC_JT2;
+ break;
+ case SMU8_SCRATCH_ENTRY_UCODE_ID_GMCON_RENG:
+ ret = UCODE_ID_GMCON_RENG;
+ break;
+ case SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_G:
+ ret = UCODE_ID_RLC_G;
+ break;
+ case SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH:
+ ret = UCODE_ID_RLC_SCRATCH;
+ break;
+ case SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM:
+ ret = UCODE_ID_RLC_SRM_ARAM;
+ break;
+ case SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM:
+ ret = UCODE_ID_RLC_SRM_DRAM;
+ break;
+ case SMU8_SCRATCH_ENTRY_UCODE_ID_DMCU_ERAM:
+ ret = UCODE_ID_DMCU_ERAM;
+ break;
+ case SMU8_SCRATCH_ENTRY_UCODE_ID_DMCU_IRAM:
+ ret = UCODE_ID_DMCU_IRAM;
+ break;
+ case SMU8_SCRATCH_ENTRY_UCODE_ID_POWER_PROFILING:
+ ret = TASK_ARG_INIT_MM_PWR_LOG;
+ break;
+ case SMU8_SCRATCH_ENTRY_DATA_ID_SDMA_HALT:
+ case SMU8_SCRATCH_ENTRY_DATA_ID_SYS_CLOCKGATING:
+ case SMU8_SCRATCH_ENTRY_DATA_ID_SDMA_RING_REGS:
+ case SMU8_SCRATCH_ENTRY_DATA_ID_NONGFX_REINIT:
+ case SMU8_SCRATCH_ENTRY_DATA_ID_SDMA_START:
+ case SMU8_SCRATCH_ENTRY_DATA_ID_IH_REGISTERS:
+ ret = TASK_ARG_REG_MMIO;
+ break;
+ case SMU8_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE:
+ ret = TASK_ARG_INIT_CLK_TABLE;
+ break;
+ }
+
+ return ret;
+}
+
+static enum cgs_ucode_id smu8_convert_fw_type_to_cgs(uint32_t fw_type)
+{
+ enum cgs_ucode_id result = CGS_UCODE_ID_MAXIMUM;
+
+ switch (fw_type) {
+ case UCODE_ID_SDMA0:
+ result = CGS_UCODE_ID_SDMA0;
+ break;
+ case UCODE_ID_SDMA1:
+ result = CGS_UCODE_ID_SDMA1;
+ break;
+ case UCODE_ID_CP_CE:
+ result = CGS_UCODE_ID_CP_CE;
+ break;
+ case UCODE_ID_CP_PFP:
+ result = CGS_UCODE_ID_CP_PFP;
+ break;
+ case UCODE_ID_CP_ME:
+ result = CGS_UCODE_ID_CP_ME;
+ break;
+ case UCODE_ID_CP_MEC_JT1:
+ result = CGS_UCODE_ID_CP_MEC_JT1;
+ break;
+ case UCODE_ID_CP_MEC_JT2:
+ result = CGS_UCODE_ID_CP_MEC_JT2;
+ break;
+ case UCODE_ID_RLC_G:
+ result = CGS_UCODE_ID_RLC_G;
+ break;
+ default:
+ break;
+ }
+
+ return result;
+}
+
+static int smu8_smu_populate_single_scratch_task(
+ struct pp_hwmgr *hwmgr,
+ enum smu8_scratch_entry fw_enum,
+ uint8_t type, bool is_last)
+{
+ uint8_t i;
+ struct smu8_smumgr *smu8_smu = hwmgr->smu_backend;
+ struct TOC *toc = (struct TOC *)smu8_smu->toc_buffer.kaddr;
+ struct SMU_Task *task = &toc->tasks[smu8_smu->toc_entry_used_count++];
+
+ task->type = type;
+ task->arg = smu8_translate_firmware_enum_to_arg(hwmgr, fw_enum);
+ task->next = is_last ? END_OF_TASK_LIST : smu8_smu->toc_entry_used_count;
+
+ for (i = 0; i < smu8_smu->scratch_buffer_length; i++)
+ if (smu8_smu->scratch_buffer[i].firmware_ID == fw_enum)
+ break;
+
+ if (i >= smu8_smu->scratch_buffer_length) {
+ pr_err("Invalid Firmware Type\n");
+ return -EINVAL;
+ }
+
+ task->addr.low = lower_32_bits(smu8_smu->scratch_buffer[i].mc_addr);
+ task->addr.high = upper_32_bits(smu8_smu->scratch_buffer[i].mc_addr);
+ task->size_bytes = smu8_smu->scratch_buffer[i].data_size;
+
+ if (SMU8_SCRATCH_ENTRY_DATA_ID_IH_REGISTERS == fw_enum) {
+ struct smu8_ih_meta_data *pIHReg_restore =
+ (struct smu8_ih_meta_data *)smu8_smu->scratch_buffer[i].kaddr;
+ pIHReg_restore->command =
+ METADATA_CMD_MODE0 | METADATA_PERFORM_ON_LOAD;
+ }
+
+ return 0;
+}
+
+static int smu8_smu_populate_single_ucode_load_task(
+ struct pp_hwmgr *hwmgr,
+ enum smu8_scratch_entry fw_enum,
+ bool is_last)
+{
+ uint8_t i;
+ struct smu8_smumgr *smu8_smu = hwmgr->smu_backend;
+ struct TOC *toc = (struct TOC *)smu8_smu->toc_buffer.kaddr;
+ struct SMU_Task *task = &toc->tasks[smu8_smu->toc_entry_used_count++];
+
+ task->type = TASK_TYPE_UCODE_LOAD;
+ task->arg = smu8_translate_firmware_enum_to_arg(hwmgr, fw_enum);
+ task->next = is_last ? END_OF_TASK_LIST : smu8_smu->toc_entry_used_count;
+
+ for (i = 0; i < smu8_smu->driver_buffer_length; i++)
+ if (smu8_smu->driver_buffer[i].firmware_ID == fw_enum)
+ break;
+
+ if (i >= smu8_smu->driver_buffer_length) {
+ pr_err("Invalid Firmware Type\n");
+ return -EINVAL;
+ }
+
+ task->addr.low = lower_32_bits(smu8_smu->driver_buffer[i].mc_addr);
+ task->addr.high = upper_32_bits(smu8_smu->driver_buffer[i].mc_addr);
+ task->size_bytes = smu8_smu->driver_buffer[i].data_size;
+
+ return 0;
+}
+
+static int smu8_smu_construct_toc_for_rlc_aram_save(struct pp_hwmgr *hwmgr)
+{
+ struct smu8_smumgr *smu8_smu = hwmgr->smu_backend;
+
+ smu8_smu->toc_entry_aram = smu8_smu->toc_entry_used_count;
+ smu8_smu_populate_single_scratch_task(hwmgr,
+ SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM,
+ TASK_TYPE_UCODE_SAVE, true);
+
+ return 0;
+}
+
+static int smu8_smu_initialize_toc_empty_job_list(struct pp_hwmgr *hwmgr)
+{
+ int i;
+ struct smu8_smumgr *smu8_smu = hwmgr->smu_backend;
+ struct TOC *toc = (struct TOC *)smu8_smu->toc_buffer.kaddr;
+
+ for (i = 0; i < NUM_JOBLIST_ENTRIES; i++)
+ toc->JobList[i] = (uint8_t)IGNORE_JOB;
+
+ return 0;
+}
+
+static int smu8_smu_construct_toc_for_vddgfx_enter(struct pp_hwmgr *hwmgr)
+{
+ struct smu8_smumgr *smu8_smu = hwmgr->smu_backend;
+ struct TOC *toc = (struct TOC *)smu8_smu->toc_buffer.kaddr;
+
+ toc->JobList[JOB_GFX_SAVE] = (uint8_t)smu8_smu->toc_entry_used_count;
+ smu8_smu_populate_single_scratch_task(hwmgr,
+ SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH,
+ TASK_TYPE_UCODE_SAVE, false);
+
+ smu8_smu_populate_single_scratch_task(hwmgr,
+ SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM,
+ TASK_TYPE_UCODE_SAVE, true);
+
+ return 0;
+}
+
+
+static int smu8_smu_construct_toc_for_vddgfx_exit(struct pp_hwmgr *hwmgr)
+{
+ struct smu8_smumgr *smu8_smu = hwmgr->smu_backend;
+ struct TOC *toc = (struct TOC *)smu8_smu->toc_buffer.kaddr;
+
+ toc->JobList[JOB_GFX_RESTORE] = (uint8_t)smu8_smu->toc_entry_used_count;
+
+ smu8_smu_populate_single_ucode_load_task(hwmgr,
+ SMU8_SCRATCH_ENTRY_UCODE_ID_CP_CE, false);
+ smu8_smu_populate_single_ucode_load_task(hwmgr,
+ SMU8_SCRATCH_ENTRY_UCODE_ID_CP_PFP, false);
+ smu8_smu_populate_single_ucode_load_task(hwmgr,
+ SMU8_SCRATCH_ENTRY_UCODE_ID_CP_ME, false);
+ smu8_smu_populate_single_ucode_load_task(hwmgr,
+ SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, false);
+
+ if (hwmgr->chip_id == CHIP_STONEY)
+ smu8_smu_populate_single_ucode_load_task(hwmgr,
+ SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, false);
+ else
+ smu8_smu_populate_single_ucode_load_task(hwmgr,
+ SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2, false);
+
+ smu8_smu_populate_single_ucode_load_task(hwmgr,
+ SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_G, false);
+
+ /* populate scratch */
+ smu8_smu_populate_single_scratch_task(hwmgr,
+ SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH,
+ TASK_TYPE_UCODE_LOAD, false);
+
+ smu8_smu_populate_single_scratch_task(hwmgr,
+ SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM,
+ TASK_TYPE_UCODE_LOAD, false);
+
+ smu8_smu_populate_single_scratch_task(hwmgr,
+ SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM,
+ TASK_TYPE_UCODE_LOAD, true);
+
+ return 0;
+}
+
+static int smu8_smu_construct_toc_for_power_profiling(struct pp_hwmgr *hwmgr)
+{
+ struct smu8_smumgr *smu8_smu = hwmgr->smu_backend;
+
+ smu8_smu->toc_entry_power_profiling_index = smu8_smu->toc_entry_used_count;
+
+ smu8_smu_populate_single_scratch_task(hwmgr,
+ SMU8_SCRATCH_ENTRY_UCODE_ID_POWER_PROFILING,
+ TASK_TYPE_INITIALIZE, true);
+ return 0;
+}
+
+static int smu8_smu_construct_toc_for_bootup(struct pp_hwmgr *hwmgr)
+{
+ struct smu8_smumgr *smu8_smu = hwmgr->smu_backend;
+
+ smu8_smu->toc_entry_initialize_index = smu8_smu->toc_entry_used_count;
+
+ smu8_smu_populate_single_ucode_load_task(hwmgr,
+ SMU8_SCRATCH_ENTRY_UCODE_ID_SDMA0, false);
+ if (hwmgr->chip_id != CHIP_STONEY)
+ smu8_smu_populate_single_ucode_load_task(hwmgr,
+ SMU8_SCRATCH_ENTRY_UCODE_ID_SDMA1, false);
+ smu8_smu_populate_single_ucode_load_task(hwmgr,
+ SMU8_SCRATCH_ENTRY_UCODE_ID_CP_CE, false);
+ smu8_smu_populate_single_ucode_load_task(hwmgr,
+ SMU8_SCRATCH_ENTRY_UCODE_ID_CP_PFP, false);
+ smu8_smu_populate_single_ucode_load_task(hwmgr,
+ SMU8_SCRATCH_ENTRY_UCODE_ID_CP_ME, false);
+ smu8_smu_populate_single_ucode_load_task(hwmgr,
+ SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, false);
+ if (hwmgr->chip_id != CHIP_STONEY)
+ smu8_smu_populate_single_ucode_load_task(hwmgr,
+ SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2, false);
+ smu8_smu_populate_single_ucode_load_task(hwmgr,
+ SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_G, true);
+
+ return 0;
+}
+
+static int smu8_smu_construct_toc_for_clock_table(struct pp_hwmgr *hwmgr)
+{
+ struct smu8_smumgr *smu8_smu = hwmgr->smu_backend;
+
+ smu8_smu->toc_entry_clock_table = smu8_smu->toc_entry_used_count;
+
+ smu8_smu_populate_single_scratch_task(hwmgr,
+ SMU8_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE,
+ TASK_TYPE_INITIALIZE, true);
+
+ return 0;
+}
+
+static int smu8_smu_construct_toc(struct pp_hwmgr *hwmgr)
+{
+ struct smu8_smumgr *smu8_smu = hwmgr->smu_backend;
+
+ smu8_smu->toc_entry_used_count = 0;
+ smu8_smu_initialize_toc_empty_job_list(hwmgr);
+ smu8_smu_construct_toc_for_rlc_aram_save(hwmgr);
+ smu8_smu_construct_toc_for_vddgfx_enter(hwmgr);
+ smu8_smu_construct_toc_for_vddgfx_exit(hwmgr);
+ smu8_smu_construct_toc_for_power_profiling(hwmgr);
+ smu8_smu_construct_toc_for_bootup(hwmgr);
+ smu8_smu_construct_toc_for_clock_table(hwmgr);
+
+ return 0;
+}
+
+static int smu8_smu_populate_firmware_entries(struct pp_hwmgr *hwmgr)
+{
+ struct smu8_smumgr *smu8_smu = hwmgr->smu_backend;
+ uint32_t firmware_type;
+ uint32_t i;
+ int ret;
+ enum cgs_ucode_id ucode_id;
+ struct cgs_firmware_info info = {0};
+
+ smu8_smu->driver_buffer_length = 0;
+
+ for (i = 0; i < ARRAY_SIZE(firmware_list); i++) {
+
+ firmware_type = smu8_translate_firmware_enum_to_arg(hwmgr,
+ firmware_list[i]);
+
+ ucode_id = smu8_convert_fw_type_to_cgs(firmware_type);
+
+ ret = cgs_get_firmware_info(hwmgr->device,
+ ucode_id, &info);
+
+ if (ret == 0) {
+ smu8_smu->driver_buffer[i].mc_addr = info.mc_addr;
+
+ smu8_smu->driver_buffer[i].data_size = info.image_size;
+
+ smu8_smu->driver_buffer[i].firmware_ID = firmware_list[i];
+ smu8_smu->driver_buffer_length++;
+ }
+ }
+
+ return 0;
+}
+
+static int smu8_smu_populate_single_scratch_entry(
+ struct pp_hwmgr *hwmgr,
+ enum smu8_scratch_entry scratch_type,
+ uint32_t ulsize_byte,
+ struct smu8_buffer_entry *entry)
+{
+ struct smu8_smumgr *smu8_smu = hwmgr->smu_backend;
+ uint32_t ulsize_aligned = SIZE_ALIGN_32(ulsize_byte);
+
+ entry->data_size = ulsize_byte;
+ entry->kaddr = (char *) smu8_smu->smu_buffer.kaddr +
+ smu8_smu->smu_buffer_used_bytes;
+ entry->mc_addr = smu8_smu->smu_buffer.mc_addr + smu8_smu->smu_buffer_used_bytes;
+ entry->firmware_ID = scratch_type;
+
+ smu8_smu->smu_buffer_used_bytes += ulsize_aligned;
+
+ return 0;
+}
+
+static int smu8_download_pptable_settings(struct pp_hwmgr *hwmgr, void **table)
+{
+ struct smu8_smumgr *smu8_smu = hwmgr->smu_backend;
+ unsigned long i;
+
+ for (i = 0; i < smu8_smu->scratch_buffer_length; i++) {
+ if (smu8_smu->scratch_buffer[i].firmware_ID
+ == SMU8_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE)
+ break;
+ }
+
+ *table = (struct SMU8_Fusion_ClkTable *)smu8_smu->scratch_buffer[i].kaddr;
+
+ smu8_send_msg_to_smc_with_parameter(hwmgr,
+ PPSMC_MSG_SetClkTableAddrHi,
+ upper_32_bits(smu8_smu->scratch_buffer[i].mc_addr));
+
+ smu8_send_msg_to_smc_with_parameter(hwmgr,
+ PPSMC_MSG_SetClkTableAddrLo,
+ lower_32_bits(smu8_smu->scratch_buffer[i].mc_addr));
+
+ smu8_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_ExecuteJob,
+ smu8_smu->toc_entry_clock_table);
+
+ smu8_send_msg_to_smc(hwmgr, PPSMC_MSG_ClkTableXferToDram);
+
+ return 0;
+}
+
+static int smu8_upload_pptable_settings(struct pp_hwmgr *hwmgr)
+{
+ struct smu8_smumgr *smu8_smu = hwmgr->smu_backend;
+ unsigned long i;
+
+ for (i = 0; i < smu8_smu->scratch_buffer_length; i++) {
+ if (smu8_smu->scratch_buffer[i].firmware_ID
+ == SMU8_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE)
+ break;
+ }
+
+ smu8_send_msg_to_smc_with_parameter(hwmgr,
+ PPSMC_MSG_SetClkTableAddrHi,
+ upper_32_bits(smu8_smu->scratch_buffer[i].mc_addr));
+
+ smu8_send_msg_to_smc_with_parameter(hwmgr,
+ PPSMC_MSG_SetClkTableAddrLo,
+ lower_32_bits(smu8_smu->scratch_buffer[i].mc_addr));
+
+ smu8_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_ExecuteJob,
+ smu8_smu->toc_entry_clock_table);
+
+ smu8_send_msg_to_smc(hwmgr, PPSMC_MSG_ClkTableXferToSmu);
+
+ return 0;
+}
+
+static int smu8_request_smu_load_fw(struct pp_hwmgr *hwmgr)
+{
+ struct smu8_smumgr *smu8_smu = hwmgr->smu_backend;
+ uint32_t smc_address;
+
+ if (!hwmgr->reload_fw) {
+ pr_info("skip reloading...\n");
+ return 0;
+ }
+
+ smu8_smu_populate_firmware_entries(hwmgr);
+
+ smu8_smu_construct_toc(hwmgr);
+
+ smc_address = SMU8_FIRMWARE_HEADER_LOCATION +
+ offsetof(struct SMU8_Firmware_Header, UcodeLoadStatus);
+
+ smu8_write_smc_sram_dword(hwmgr, smc_address, 0, smc_address+4);
+
+ smu8_send_msg_to_smc_with_parameter(hwmgr,
+ PPSMC_MSG_DriverDramAddrHi,
+ upper_32_bits(smu8_smu->toc_buffer.mc_addr));
+
+ smu8_send_msg_to_smc_with_parameter(hwmgr,
+ PPSMC_MSG_DriverDramAddrLo,
+ lower_32_bits(smu8_smu->toc_buffer.mc_addr));
+
+ smu8_send_msg_to_smc(hwmgr, PPSMC_MSG_InitJobs);
+
+ smu8_send_msg_to_smc_with_parameter(hwmgr,
+ PPSMC_MSG_ExecuteJob,
+ smu8_smu->toc_entry_aram);
+ smu8_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_ExecuteJob,
+ smu8_smu->toc_entry_power_profiling_index);
+
+ return smu8_send_msg_to_smc_with_parameter(hwmgr,
+ PPSMC_MSG_ExecuteJob,
+ smu8_smu->toc_entry_initialize_index);
+}
+
+static int smu8_start_smu(struct pp_hwmgr *hwmgr)
+{
+ int ret = 0;
+ uint32_t fw_to_check = 0;
+ struct amdgpu_device *adev = hwmgr->adev;
+
+ uint32_t index = SMN_MP1_SRAM_START_ADDR +
+ SMU8_FIRMWARE_HEADER_LOCATION +
+ offsetof(struct SMU8_Firmware_Header, Version);
+
+
+ if (hwmgr == NULL || hwmgr->device == NULL)
+ return -EINVAL;
+
+ cgs_write_register(hwmgr->device, mmMP0PUB_IND_INDEX, index);
+ hwmgr->smu_version = cgs_read_register(hwmgr->device, mmMP0PUB_IND_DATA);
+ adev->pm.fw_version = hwmgr->smu_version >> 8;
+
+ fw_to_check = UCODE_ID_RLC_G_MASK |
+ UCODE_ID_SDMA0_MASK |
+ UCODE_ID_SDMA1_MASK |
+ UCODE_ID_CP_CE_MASK |
+ UCODE_ID_CP_ME_MASK |
+ UCODE_ID_CP_PFP_MASK |
+ UCODE_ID_CP_MEC_JT1_MASK |
+ UCODE_ID_CP_MEC_JT2_MASK;
+
+ if (hwmgr->chip_id == CHIP_STONEY)
+ fw_to_check &= ~(UCODE_ID_SDMA1_MASK | UCODE_ID_CP_MEC_JT2_MASK);
+
+ ret = smu8_request_smu_load_fw(hwmgr);
+ if (ret)
+ pr_err("SMU firmware load failed\n");
+
+ smu8_check_fw_load_finish(hwmgr, fw_to_check);
+
+ ret = smu8_load_mec_firmware(hwmgr);
+ if (ret)
+ pr_err("Mec Firmware load failed\n");
+
+ return ret;
+}
+
+static int smu8_smu_init(struct pp_hwmgr *hwmgr)
+{
+ int ret = 0;
+ struct smu8_smumgr *smu8_smu;
+
+ smu8_smu = kzalloc(sizeof(struct smu8_smumgr), GFP_KERNEL);
+ if (smu8_smu == NULL)
+ return -ENOMEM;
+
+ hwmgr->smu_backend = smu8_smu;
+
+ smu8_smu->toc_buffer.data_size = 4096;
+ smu8_smu->smu_buffer.data_size =
+ ALIGN(UCODE_ID_RLC_SCRATCH_SIZE_BYTE, 32) +
+ ALIGN(UCODE_ID_RLC_SRM_ARAM_SIZE_BYTE, 32) +
+ ALIGN(UCODE_ID_RLC_SRM_DRAM_SIZE_BYTE, 32) +
+ ALIGN(sizeof(struct SMU8_MultimediaPowerLogData), 32) +
+ ALIGN(sizeof(struct SMU8_Fusion_ClkTable), 32);
+
+ ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
+ smu8_smu->toc_buffer.data_size,
+ PAGE_SIZE,
+ AMDGPU_GEM_DOMAIN_VRAM,
+ &smu8_smu->toc_buffer.handle,
+ &smu8_smu->toc_buffer.mc_addr,
+ &smu8_smu->toc_buffer.kaddr);
+ if (ret)
+ goto err2;
+
+ ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
+ smu8_smu->smu_buffer.data_size,
+ PAGE_SIZE,
+ AMDGPU_GEM_DOMAIN_VRAM,
+ &smu8_smu->smu_buffer.handle,
+ &smu8_smu->smu_buffer.mc_addr,
+ &smu8_smu->smu_buffer.kaddr);
+ if (ret)
+ goto err1;
+
+ if (0 != smu8_smu_populate_single_scratch_entry(hwmgr,
+ SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH,
+ UCODE_ID_RLC_SCRATCH_SIZE_BYTE,
+ &smu8_smu->scratch_buffer[smu8_smu->scratch_buffer_length++])) {
+ pr_err("Error when Populate Firmware Entry.\n");
+ goto err0;
+ }
+
+ if (0 != smu8_smu_populate_single_scratch_entry(hwmgr,
+ SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM,
+ UCODE_ID_RLC_SRM_ARAM_SIZE_BYTE,
+ &smu8_smu->scratch_buffer[smu8_smu->scratch_buffer_length++])) {
+ pr_err("Error when Populate Firmware Entry.\n");
+ goto err0;
+ }
+ if (0 != smu8_smu_populate_single_scratch_entry(hwmgr,
+ SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM,
+ UCODE_ID_RLC_SRM_DRAM_SIZE_BYTE,
+ &smu8_smu->scratch_buffer[smu8_smu->scratch_buffer_length++])) {
+ pr_err("Error when Populate Firmware Entry.\n");
+ goto err0;
+ }
+
+ if (0 != smu8_smu_populate_single_scratch_entry(hwmgr,
+ SMU8_SCRATCH_ENTRY_UCODE_ID_POWER_PROFILING,
+ sizeof(struct SMU8_MultimediaPowerLogData),
+ &smu8_smu->scratch_buffer[smu8_smu->scratch_buffer_length++])) {
+ pr_err("Error when Populate Firmware Entry.\n");
+ goto err0;
+ }
+
+ if (0 != smu8_smu_populate_single_scratch_entry(hwmgr,
+ SMU8_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE,
+ sizeof(struct SMU8_Fusion_ClkTable),
+ &smu8_smu->scratch_buffer[smu8_smu->scratch_buffer_length++])) {
+ pr_err("Error when Populate Firmware Entry.\n");
+ goto err0;
+ }
+
+ return 0;
+
+err0:
+ amdgpu_bo_free_kernel(&smu8_smu->smu_buffer.handle,
+ &smu8_smu->smu_buffer.mc_addr,
+ &smu8_smu->smu_buffer.kaddr);
+err1:
+ amdgpu_bo_free_kernel(&smu8_smu->toc_buffer.handle,
+ &smu8_smu->toc_buffer.mc_addr,
+ &smu8_smu->toc_buffer.kaddr);
+err2:
+ kfree(smu8_smu);
+ return -EINVAL;
+}
+
+static int smu8_smu_fini(struct pp_hwmgr *hwmgr)
+{
+ struct smu8_smumgr *smu8_smu;
+
+ if (hwmgr == NULL || hwmgr->device == NULL)
+ return -EINVAL;
+
+ smu8_smu = hwmgr->smu_backend;
+ if (smu8_smu) {
+ amdgpu_bo_free_kernel(&smu8_smu->toc_buffer.handle,
+ &smu8_smu->toc_buffer.mc_addr,
+ &smu8_smu->toc_buffer.kaddr);
+ amdgpu_bo_free_kernel(&smu8_smu->smu_buffer.handle,
+ &smu8_smu->smu_buffer.mc_addr,
+ &smu8_smu->smu_buffer.kaddr);
+ kfree(smu8_smu);
+ }
+
+ return 0;
+}
+
+static bool smu8_dpm_check_smu_features(struct pp_hwmgr *hwmgr,
+ unsigned long check_feature)
+{
+ int result;
+ unsigned long features;
+
+ result = smu8_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_GetFeatureStatus, 0);
+ if (result == 0) {
+ features = smum_get_argument(hwmgr);
+ if (features & check_feature)
+ return true;
+ }
+
+ return false;
+}
+
+static bool smu8_is_dpm_running(struct pp_hwmgr *hwmgr)
+{
+ if (smu8_dpm_check_smu_features(hwmgr, SMU_EnabledFeatureScoreboard_SclkDpmOn))
+ return true;
+ return false;
+}
+
+const struct pp_smumgr_func smu8_smu_funcs = {
+ .smu_init = smu8_smu_init,
+ .smu_fini = smu8_smu_fini,
+ .start_smu = smu8_start_smu,
+ .check_fw_load_finish = smu8_check_fw_load_finish,
+ .request_smu_load_fw = NULL,
+ .request_smu_load_specific_fw = NULL,
+ .get_argument = smu8_get_argument,
+ .send_msg_to_smc = smu8_send_msg_to_smc,
+ .send_msg_to_smc_with_parameter = smu8_send_msg_to_smc_with_parameter,
+ .download_pptable_settings = smu8_download_pptable_settings,
+ .upload_pptable_settings = smu8_upload_pptable_settings,
+ .is_dpm_running = smu8_is_dpm_running,
+};
+
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.h b/drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.h
new file mode 100644
index 000000000000..c7b61222d258
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.h
@@ -0,0 +1,99 @@
+/*
+ * 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_SMUMGR_H_
+#define _SMU8_SMUMGR_H_
+
+
+#define MAX_NUM_FIRMWARE 8
+#define MAX_NUM_SCRATCH 11
+#define SMU8_SCRATCH_SIZE_NONGFX_CLOCKGATING 1024
+#define SMU8_SCRATCH_SIZE_NONGFX_GOLDENSETTING 2048
+#define SMU8_SCRATCH_SIZE_SDMA_METADATA 1024
+#define SMU8_SCRATCH_SIZE_IH ((2*256+1)*4)
+
+#define SMU_EnabledFeatureScoreboard_SclkDpmOn 0x00200000
+
+enum smu8_scratch_entry {
+ SMU8_SCRATCH_ENTRY_UCODE_ID_SDMA0 = 0,
+ SMU8_SCRATCH_ENTRY_UCODE_ID_SDMA1,
+ SMU8_SCRATCH_ENTRY_UCODE_ID_CP_CE,
+ SMU8_SCRATCH_ENTRY_UCODE_ID_CP_PFP,
+ SMU8_SCRATCH_ENTRY_UCODE_ID_CP_ME,
+ SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1,
+ SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2,
+ SMU8_SCRATCH_ENTRY_UCODE_ID_GMCON_RENG,
+ SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_G,
+ SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH,
+ SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM,
+ SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM,
+ SMU8_SCRATCH_ENTRY_UCODE_ID_DMCU_ERAM,
+ SMU8_SCRATCH_ENTRY_UCODE_ID_DMCU_IRAM,
+ SMU8_SCRATCH_ENTRY_UCODE_ID_POWER_PROFILING,
+ SMU8_SCRATCH_ENTRY_DATA_ID_SDMA_HALT,
+ SMU8_SCRATCH_ENTRY_DATA_ID_SYS_CLOCKGATING,
+ SMU8_SCRATCH_ENTRY_DATA_ID_SDMA_RING_REGS,
+ SMU8_SCRATCH_ENTRY_DATA_ID_NONGFX_REINIT,
+ SMU8_SCRATCH_ENTRY_DATA_ID_SDMA_START,
+ SMU8_SCRATCH_ENTRY_DATA_ID_IH_REGISTERS,
+ SMU8_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE
+};
+
+struct smu8_buffer_entry {
+ uint32_t data_size;
+ uint64_t mc_addr;
+ void *kaddr;
+ enum smu8_scratch_entry firmware_ID;
+ struct amdgpu_bo *handle; /* as bo handle used when release bo */
+};
+
+struct smu8_register_index_data_pair {
+ uint32_t offset;
+ uint32_t value;
+};
+
+struct smu8_ih_meta_data {
+ uint32_t command;
+ struct smu8_register_index_data_pair register_index_value_pair[1];
+};
+
+struct smu8_smumgr {
+ uint8_t driver_buffer_length;
+ uint8_t scratch_buffer_length;
+ uint16_t toc_entry_used_count;
+ uint16_t toc_entry_initialize_index;
+ uint16_t toc_entry_power_profiling_index;
+ uint16_t toc_entry_aram;
+ uint16_t toc_entry_ih_register_restore_task_index;
+ uint16_t toc_entry_clock_table;
+ uint16_t ih_register_restore_task_size;
+ uint16_t smu_buffer_used_bytes;
+
+ struct smu8_buffer_entry toc_buffer;
+ struct smu8_buffer_entry smu_buffer;
+ struct smu8_buffer_entry firmware_buffer;
+ struct smu8_buffer_entry driver_buffer[MAX_NUM_FIRMWARE];
+ struct smu8_buffer_entry meta_data_buffer[MAX_NUM_FIRMWARE];
+ struct smu8_buffer_entry scratch_buffer[MAX_NUM_SCRATCH];
+};
+
+#endif
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c
index 867388456530..c28b60aae5f8 100644
--- a/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c
@@ -28,7 +28,6 @@
#include <linux/types.h>
#include <drm/amdgpu_drm.h>
#include "smumgr.h"
-#include "cgs_common.h"
MODULE_FIRMWARE("amdgpu/topaz_smc.bin");
MODULE_FIRMWARE("amdgpu/topaz_k_smc.bin");
@@ -44,6 +43,7 @@ MODULE_FIRMWARE("amdgpu/polaris11_k_smc.bin");
MODULE_FIRMWARE("amdgpu/polaris12_smc.bin");
MODULE_FIRMWARE("amdgpu/vega10_smc.bin");
MODULE_FIRMWARE("amdgpu/vega10_acg_smc.bin");
+MODULE_FIRMWARE("amdgpu/vega12_smc.bin");
int smum_thermal_avfs_enable(struct pp_hwmgr *hwmgr)
{
@@ -144,57 +144,6 @@ int smum_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr,
hwmgr, msg, parameter);
}
-int smu_allocate_memory(void *device, uint32_t size,
- enum cgs_gpu_mem_type type,
- uint32_t byte_align, uint64_t *mc_addr,
- void **kptr, void *handle)
-{
- int ret = 0;
- cgs_handle_t cgs_handle;
-
- if (device == NULL || handle == NULL ||
- mc_addr == NULL || kptr == NULL)
- return -EINVAL;
-
- ret = cgs_alloc_gpu_mem(device, type, size, byte_align,
- (cgs_handle_t *)handle);
- if (ret)
- return -ENOMEM;
-
- cgs_handle = *(cgs_handle_t *)handle;
-
- ret = cgs_gmap_gpu_mem(device, cgs_handle, mc_addr);
- if (ret)
- goto error_gmap;
-
- ret = cgs_kmap_gpu_mem(device, cgs_handle, kptr);
- if (ret)
- goto error_kmap;
-
- return 0;
-
-error_kmap:
- cgs_gunmap_gpu_mem(device, cgs_handle);
-
-error_gmap:
- cgs_free_gpu_mem(device, cgs_handle);
- return ret;
-}
-
-int smu_free_memory(void *device, void *handle)
-{
- cgs_handle_t cgs_handle = (cgs_handle_t)handle;
-
- if (device == NULL || handle == NULL)
- return -EINVAL;
-
- cgs_kunmap_gpu_mem(device, cgs_handle);
- cgs_gunmap_gpu_mem(device, cgs_handle);
- cgs_free_gpu_mem(device, cgs_handle);
-
- return 0;
-}
-
int smum_init_smc_table(struct pp_hwmgr *hwmgr)
{
if (NULL != hwmgr->smumgr_funcs->init_smc_table)
@@ -236,16 +185,6 @@ bool smum_is_dpm_running(struct pp_hwmgr *hwmgr)
return true;
}
-int smum_populate_requested_graphic_levels(struct pp_hwmgr *hwmgr,
- struct amd_pp_profile *request)
-{
- if (hwmgr->smumgr_funcs->populate_requested_graphic_levels)
- return hwmgr->smumgr_funcs->populate_requested_graphic_levels(
- hwmgr, request);
-
- return 0;
-}
-
bool smum_is_hw_avfs_present(struct pp_hwmgr *hwmgr)
{
if (hwmgr->smumgr_funcs->is_hw_avfs_present)
@@ -253,3 +192,19 @@ bool smum_is_hw_avfs_present(struct pp_hwmgr *hwmgr)
return false;
}
+
+int smum_update_dpm_settings(struct pp_hwmgr *hwmgr, void *profile_setting)
+{
+ if (hwmgr->smumgr_funcs->update_dpm_settings)
+ return hwmgr->smumgr_funcs->update_dpm_settings(hwmgr, profile_setting);
+
+ return -EINVAL;
+}
+
+int smum_smc_table_manager(struct pp_hwmgr *hwmgr, uint8_t *table, uint16_t table_id, bool rw)
+{
+ if (hwmgr->smumgr_funcs->smc_table_manager)
+ return hwmgr->smumgr_funcs->smc_table_manager(hwmgr, table, table_id, rw);
+
+ return -EINVAL;
+}
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.c
index 79e5c05571bc..b51d7468c3e7 100644
--- a/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.c
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.c
@@ -222,7 +222,6 @@ static int tonga_start_smu(struct pp_hwmgr *hwmgr)
static int tonga_smu_init(struct pp_hwmgr *hwmgr)
{
struct tonga_smumgr *tonga_priv = NULL;
- int i;
tonga_priv = kzalloc(sizeof(struct tonga_smumgr), GFP_KERNEL);
if (tonga_priv == NULL)
@@ -230,11 +229,10 @@ static int tonga_smu_init(struct pp_hwmgr *hwmgr)
hwmgr->smu_backend = tonga_priv;
- if (smu7_init(hwmgr))
+ if (smu7_init(hwmgr)) {
+ kfree(tonga_priv);
return -EINVAL;
-
- for (i = 0; i < SMU72_MAX_LEVELS_GRAPHICS; i++)
- tonga_priv->activity_target[i] = 30;
+ }
return 0;
}
@@ -416,7 +414,7 @@ static int tonga_populate_cac_tables(struct pp_hwmgr *hwmgr,
convert_to_vid(vddc_lookup_table->entries[index].us_cac_high);
}
- if ((data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID2)) {
+ if (data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID2) {
/* We are populating vddgfx CAC data to BapmVddgfx table in split mode */
for (count = 0; count < vddgfx_level_count; count++) {
index = phm_get_voltage_index(vddgfx_lookup_table,
@@ -612,7 +610,6 @@ static int tonga_calculate_sclk_params(struct pp_hwmgr *hwmgr,
static int tonga_populate_single_graphic_level(struct pp_hwmgr *hwmgr,
uint32_t engine_clock,
- uint16_t sclk_activity_level_threshold,
SMU72_Discrete_GraphicsLevel *graphic_level)
{
int result;
@@ -620,12 +617,18 @@ static int tonga_populate_single_graphic_level(struct pp_hwmgr *hwmgr,
struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
struct phm_ppt_v1_information *pptable_info =
(struct phm_ppt_v1_information *)(hwmgr->pptable);
+ phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_table = NULL;
result = tonga_calculate_sclk_params(hwmgr, engine_clock, graphic_level);
+ if (hwmgr->od_enabled)
+ vdd_dep_table = (phm_ppt_v1_clock_voltage_dependency_table *)&data->odn_dpm_table.vdd_dependency_on_sclk;
+ else
+ vdd_dep_table = pptable_info->vdd_dep_on_sclk;
+
/* populate graphics levels*/
result = tonga_get_dependency_volt_by_clk(hwmgr,
- pptable_info->vdd_dep_on_sclk, engine_clock,
+ vdd_dep_table, engine_clock,
&graphic_level->MinVoltage, &mvdd);
PP_ASSERT_WITH_CODE((!result),
"can not find VDDC voltage value for VDDC "
@@ -634,7 +637,7 @@ static int tonga_populate_single_graphic_level(struct pp_hwmgr *hwmgr,
/* SCLK frequency in units of 10KHz*/
graphic_level->SclkFrequency = engine_clock;
/* Indicates maximum activity level for this performance level. 50% for now*/
- graphic_level->ActivityLevel = sclk_activity_level_threshold;
+ graphic_level->ActivityLevel = data->current_profile_setting.sclk_activity;
graphic_level->CcPwrDynRm = 0;
graphic_level->CcPwrDynRm1 = 0;
@@ -642,8 +645,8 @@ static int tonga_populate_single_graphic_level(struct pp_hwmgr *hwmgr,
graphic_level->EnabledForActivity = 0;
/* this level can be used for throttling.*/
graphic_level->EnabledForThrottle = 1;
- graphic_level->UpHyst = 0;
- graphic_level->DownHyst = 0;
+ graphic_level->UpHyst = data->current_profile_setting.sclk_up_hyst;
+ graphic_level->DownHyst = data->current_profile_setting.sclk_down_hyst;
graphic_level->VoltageDownHyst = 0;
graphic_level->PowerThrottle = 0;
@@ -702,7 +705,6 @@ static int tonga_populate_all_graphic_levels(struct pp_hwmgr *hwmgr)
for (i = 0; i < dpm_table->sclk_table.count; i++) {
result = tonga_populate_single_graphic_level(hwmgr,
dpm_table->sclk_table.dpm_levels[i].value,
- (uint16_t)smu_data->activity_target[i],
&(smu_data->smc_state_table.GraphicsLevel[i]));
if (result != 0)
return result;
@@ -966,10 +968,16 @@ static int tonga_populate_single_memory_level(
uint32_t mclk_stutter_mode_threshold = 30000;
uint32_t mclk_edc_enable_threshold = 40000;
uint32_t mclk_strobe_mode_threshold = 40000;
+ phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_table = NULL;
- if (NULL != pptable_info->vdd_dep_on_mclk) {
+ if (hwmgr->od_enabled)
+ vdd_dep_table = (phm_ppt_v1_clock_voltage_dependency_table *)&data->odn_dpm_table.vdd_dependency_on_mclk;
+ else
+ vdd_dep_table = pptable_info->vdd_dep_on_mclk;
+
+ if (NULL != vdd_dep_table) {
result = tonga_get_dependency_volt_by_clk(hwmgr,
- pptable_info->vdd_dep_on_mclk,
+ vdd_dep_table,
memory_clock,
&memory_level->MinVoltage, &mvdd);
PP_ASSERT_WITH_CODE(
@@ -986,12 +994,12 @@ static int tonga_populate_single_memory_level(
memory_level->EnabledForThrottle = 1;
memory_level->EnabledForActivity = 0;
- memory_level->UpHyst = 0;
- memory_level->DownHyst = 100;
+ memory_level->UpHyst = data->current_profile_setting.mclk_up_hyst;
+ memory_level->DownHyst = data->current_profile_setting.mclk_down_hyst;
memory_level->VoltageDownHyst = 0;
/* Indicates maximum activity level for this performance level.*/
- memory_level->ActivityLevel = (uint16_t)data->mclk_activity_target;
+ memory_level->ActivityLevel = data->current_profile_setting.mclk_activity;
memory_level->StutterEnable = 0;
memory_level->StrobeEnable = 0;
memory_level->EdcReadEnable = 0;
@@ -1281,7 +1289,7 @@ static int tonga_populate_smc_acpi_level(struct pp_hwmgr *hwmgr,
table->MemoryACPILevel.VoltageDownHyst = 0;
/* Indicates maximum activity level for this performance level.*/
table->MemoryACPILevel.ActivityLevel =
- PP_HOST_TO_SMC_US((uint16_t)data->mclk_activity_target);
+ PP_HOST_TO_SMC_US(data->current_profile_setting.mclk_activity);
table->MemoryACPILevel.StutterEnable = 0;
table->MemoryACPILevel.StrobeEnable = 0;
@@ -1617,19 +1625,12 @@ static int tonga_populate_clock_stretcher_data_table(struct pp_hwmgr *hwmgr)
struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table =
table_info->vdd_dep_on_sclk;
uint32_t hw_revision, dev_id;
- struct cgs_system_info sys_info = {0};
+ struct amdgpu_device *adev = hwmgr->adev;
stretch_amount = (uint8_t)table_info->cac_dtp_table->usClockStretchAmount;
- sys_info.size = sizeof(struct cgs_system_info);
-
- sys_info.info_id = CGS_SYSTEM_INFO_PCIE_REV;
- cgs_query_system_info(hwmgr->device, &sys_info);
- hw_revision = (uint32_t)sys_info.value;
-
- sys_info.info_id = CGS_SYSTEM_INFO_PCIE_DEV;
- cgs_query_system_info(hwmgr->device, &sys_info);
- dev_id = (uint32_t)sys_info.value;
+ hw_revision = adev->pdev->revision;
+ dev_id = adev->pdev->device;
/* Read SMU_Eefuse to read and calculate RO and determine
* if the part is SS or FF. if RO >= 1660MHz, part is FF.
@@ -1699,7 +1700,7 @@ static int tonga_populate_clock_stretcher_data_table(struct pp_hwmgr *hwmgr)
phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_ClockStretcher);
PP_ASSERT_WITH_CODE(false,
- "Stretch Amount in PPTable not supported\n",
+ "Stretch Amount in PPTable not supported",
return -EINVAL);
}
@@ -2257,42 +2258,6 @@ static void tonga_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr)
smu_data->power_tune_defaults = &tonga_power_tune_data_set_array[0];
}
-static void tonga_save_default_power_profile(struct pp_hwmgr *hwmgr)
-{
- struct tonga_smumgr *data = (struct tonga_smumgr *)(hwmgr->smu_backend);
- struct SMU72_Discrete_GraphicsLevel *levels =
- data->smc_state_table.GraphicsLevel;
- unsigned min_level = 1;
-
- hwmgr->default_gfx_power_profile.activity_threshold =
- be16_to_cpu(levels[0].ActivityLevel);
- hwmgr->default_gfx_power_profile.up_hyst = levels[0].UpHyst;
- hwmgr->default_gfx_power_profile.down_hyst = levels[0].DownHyst;
- hwmgr->default_gfx_power_profile.type = AMD_PP_GFX_PROFILE;
-
- hwmgr->default_compute_power_profile = hwmgr->default_gfx_power_profile;
- hwmgr->default_compute_power_profile.type = AMD_PP_COMPUTE_PROFILE;
-
- /* Workaround compute SDMA instability: disable lowest SCLK
- * DPM level. Optimize compute power profile: Use only highest
- * 2 power levels (if more than 2 are available), Hysteresis:
- * 0ms up, 5ms down
- */
- if (data->smc_state_table.GraphicsDpmLevelCount > 2)
- min_level = data->smc_state_table.GraphicsDpmLevelCount - 2;
- else if (data->smc_state_table.GraphicsDpmLevelCount == 2)
- min_level = 1;
- else
- min_level = 0;
- hwmgr->default_compute_power_profile.min_sclk =
- be32_to_cpu(levels[min_level].SclkFrequency);
- hwmgr->default_compute_power_profile.up_hyst = 0;
- hwmgr->default_compute_power_profile.down_hyst = 5;
-
- hwmgr->gfx_power_profile = hwmgr->default_gfx_power_profile;
- hwmgr->compute_power_profile = hwmgr->default_compute_power_profile;
-}
-
static int tonga_init_smc_table(struct pp_hwmgr *hwmgr)
{
int result;
@@ -2434,7 +2399,7 @@ static int tonga_init_smc_table(struct pp_hwmgr *hwmgr)
result = tonga_populate_vr_config(hwmgr, table);
PP_ASSERT_WITH_CODE(!result,
"Failed to populate VRConfig setting !", return result);
-
+ data->vr_config = table->VRConfig;
table->ThermGpio = 17;
table->SclkStepSize = 0x4000;
@@ -2501,7 +2466,6 @@ static int tonga_init_smc_table(struct pp_hwmgr *hwmgr)
for (i = 0; i < SMU72_MAX_ENTRIES_SMIO; i++)
table->Smio[i] = PP_HOST_TO_SMC_UL(table->Smio[i]);
-
CONVERT_FROM_HOST_TO_SMC_UL(table->SystemFlags);
CONVERT_FROM_HOST_TO_SMC_UL(table->VRConfig);
CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMask1);
@@ -2535,8 +2499,6 @@ static int tonga_init_smc_table(struct pp_hwmgr *hwmgr)
PP_ASSERT_WITH_CODE((!result),
"Failed to populate initialize MC Reg table !", return result);
- tonga_save_default_power_profile(hwmgr);
-
return 0;
}
@@ -2612,7 +2574,7 @@ static int tonga_thermal_setup_fan_table(struct pp_hwmgr *hwmgr)
fan_table.TempRespLim = cpu_to_be16(5);
- reference_clock = smu7_get_xclk(hwmgr);
+ reference_clock = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev);
fan_table.RefreshPeriod = cpu_to_be32((hwmgr->thermal_controller.advanceFanControlParameters.ulCycleDelay * reference_clock) / 1600);
@@ -3254,29 +3216,100 @@ static bool tonga_is_dpm_running(struct pp_hwmgr *hwmgr)
? true : false;
}
-static int tonga_populate_requested_graphic_levels(struct pp_hwmgr *hwmgr,
- struct amd_pp_profile *request)
+static int tonga_update_dpm_settings(struct pp_hwmgr *hwmgr,
+ void *profile_setting)
{
+ struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
struct tonga_smumgr *smu_data = (struct tonga_smumgr *)
(hwmgr->smu_backend);
+ struct profile_mode_setting *setting;
struct SMU72_Discrete_GraphicsLevel *levels =
smu_data->smc_state_table.GraphicsLevel;
uint32_t array = smu_data->smu7_data.dpm_table_start +
offsetof(SMU72_Discrete_DpmTable, GraphicsLevel);
- uint32_t array_size = sizeof(struct SMU72_Discrete_GraphicsLevel) *
- SMU72_MAX_LEVELS_GRAPHICS;
+
+ uint32_t mclk_array = smu_data->smu7_data.dpm_table_start +
+ offsetof(SMU72_Discrete_DpmTable, MemoryLevel);
+ struct SMU72_Discrete_MemoryLevel *mclk_levels =
+ smu_data->smc_state_table.MemoryLevel;
uint32_t i;
+ uint32_t offset, up_hyst_offset, down_hyst_offset, clk_activity_offset, tmp;
+
+ if (profile_setting == NULL)
+ return -EINVAL;
+
+ setting = (struct profile_mode_setting *)profile_setting;
- for (i = 0; i < smu_data->smc_state_table.GraphicsDpmLevelCount; i++) {
- levels[i].ActivityLevel =
- cpu_to_be16(request->activity_threshold);
- levels[i].EnabledForActivity = 1;
- levels[i].UpHyst = request->up_hyst;
- levels[i].DownHyst = request->down_hyst;
+ if (setting->bupdate_sclk) {
+ if (!data->sclk_dpm_key_disabled)
+ smum_send_msg_to_smc(hwmgr, PPSMC_MSG_SCLKDPM_FreezeLevel);
+ for (i = 0; i < smu_data->smc_state_table.GraphicsDpmLevelCount; i++) {
+ if (levels[i].ActivityLevel !=
+ cpu_to_be16(setting->sclk_activity)) {
+ levels[i].ActivityLevel = cpu_to_be16(setting->sclk_activity);
+
+ clk_activity_offset = array + (sizeof(SMU72_Discrete_GraphicsLevel) * i)
+ + offsetof(SMU72_Discrete_GraphicsLevel, ActivityLevel);
+ offset = clk_activity_offset & ~0x3;
+ tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset));
+ tmp = phm_set_field_to_u32(clk_activity_offset, tmp, levels[i].ActivityLevel, sizeof(uint16_t));
+ cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp));
+
+ }
+ if (levels[i].UpHyst != setting->sclk_up_hyst ||
+ levels[i].DownHyst != setting->sclk_down_hyst) {
+ levels[i].UpHyst = setting->sclk_up_hyst;
+ levels[i].DownHyst = setting->sclk_down_hyst;
+ up_hyst_offset = array + (sizeof(SMU72_Discrete_GraphicsLevel) * i)
+ + offsetof(SMU72_Discrete_GraphicsLevel, UpHyst);
+ down_hyst_offset = array + (sizeof(SMU72_Discrete_GraphicsLevel) * i)
+ + offsetof(SMU72_Discrete_GraphicsLevel, DownHyst);
+ offset = up_hyst_offset & ~0x3;
+ tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset));
+ tmp = phm_set_field_to_u32(up_hyst_offset, tmp, levels[i].UpHyst, sizeof(uint8_t));
+ tmp = phm_set_field_to_u32(down_hyst_offset, tmp, levels[i].DownHyst, sizeof(uint8_t));
+ cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp));
+ }
+ }
+ if (!data->sclk_dpm_key_disabled)
+ smum_send_msg_to_smc(hwmgr, PPSMC_MSG_SCLKDPM_UnfreezeLevel);
}
- return smu7_copy_bytes_to_smc(hwmgr, array, (uint8_t *)levels,
- array_size, SMC_RAM_END);
+ if (setting->bupdate_mclk) {
+ if (!data->mclk_dpm_key_disabled)
+ smum_send_msg_to_smc(hwmgr, PPSMC_MSG_MCLKDPM_FreezeLevel);
+ for (i = 0; i < smu_data->smc_state_table.MemoryDpmLevelCount; i++) {
+ if (mclk_levels[i].ActivityLevel !=
+ cpu_to_be16(setting->mclk_activity)) {
+ mclk_levels[i].ActivityLevel = cpu_to_be16(setting->mclk_activity);
+
+ clk_activity_offset = mclk_array + (sizeof(SMU72_Discrete_MemoryLevel) * i)
+ + offsetof(SMU72_Discrete_MemoryLevel, ActivityLevel);
+ offset = clk_activity_offset & ~0x3;
+ tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset));
+ tmp = phm_set_field_to_u32(clk_activity_offset, tmp, mclk_levels[i].ActivityLevel, sizeof(uint16_t));
+ cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp));
+
+ }
+ if (mclk_levels[i].UpHyst != setting->mclk_up_hyst ||
+ mclk_levels[i].DownHyst != setting->mclk_down_hyst) {
+ mclk_levels[i].UpHyst = setting->mclk_up_hyst;
+ mclk_levels[i].DownHyst = setting->mclk_down_hyst;
+ up_hyst_offset = mclk_array + (sizeof(SMU72_Discrete_MemoryLevel) * i)
+ + offsetof(SMU72_Discrete_MemoryLevel, UpHyst);
+ down_hyst_offset = mclk_array + (sizeof(SMU72_Discrete_MemoryLevel) * i)
+ + offsetof(SMU72_Discrete_MemoryLevel, DownHyst);
+ offset = up_hyst_offset & ~0x3;
+ tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset));
+ tmp = phm_set_field_to_u32(up_hyst_offset, tmp, mclk_levels[i].UpHyst, sizeof(uint8_t));
+ tmp = phm_set_field_to_u32(down_hyst_offset, tmp, mclk_levels[i].DownHyst, sizeof(uint8_t));
+ cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp));
+ }
+ }
+ if (!data->mclk_dpm_key_disabled)
+ smum_send_msg_to_smc(hwmgr, PPSMC_MSG_MCLKDPM_UnfreezeLevel);
+ }
+ return 0;
}
const struct pp_smumgr_func tonga_smu_funcs = {
@@ -3301,5 +3334,5 @@ const struct pp_smumgr_func tonga_smu_funcs = {
.get_mac_definition = tonga_get_mac_definition,
.initialize_mc_reg_table = tonga_initialize_mc_reg_table,
.is_dpm_running = tonga_is_dpm_running,
- .populate_requested_graphic_levels = tonga_populate_requested_graphic_levels,
+ .update_dpm_settings = tonga_update_dpm_settings,
};
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.h b/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.h
index 5d70a00348e2..d664fedd3d85 100644
--- a/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.h
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.h
@@ -69,9 +69,6 @@ struct tonga_smumgr {
const struct tonga_pt_defaults *power_tune_defaults;
SMU72_Discrete_MCRegisters mc_regs;
struct tonga_mc_reg_table mc_reg_table;
-
- uint32_t activity_target[SMU72_MAX_LEVELS_GRAPHICS];
-
};
#endif
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.c
index f6f39d01d227..4aafb043bcb0 100644
--- a/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.c
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.c
@@ -25,13 +25,12 @@
#include "vega10_inc.h"
#include "pp_soc15.h"
#include "vega10_smumgr.h"
+#include "vega10_hwmgr.h"
#include "vega10_ppsmc.h"
#include "smu9_driver_if.h"
-
#include "ppatomctrl.h"
#include "pp_debug.h"
-#include "smu_ucode_xfer_vi.h"
-#include "smu7_smumgr.h"
+
#define AVFS_EN_MSB 1568
#define AVFS_EN_LSB 1568
@@ -83,16 +82,17 @@ static bool vega10_is_smc_ram_running(struct pp_hwmgr *hwmgr)
static uint32_t vega10_wait_for_response(struct pp_hwmgr *hwmgr)
{
uint32_t reg;
-
- if (!vega10_is_smc_ram_running(hwmgr))
- return -EINVAL;
+ uint32_t ret;
reg = soc15_get_register_offset(MP1_HWID, 0,
mmMP1_SMN_C2PMSG_90_BASE_IDX, mmMP1_SMN_C2PMSG_90);
- phm_wait_for_register_unequal(hwmgr, reg,
+ ret = phm_wait_for_register_unequal(hwmgr, reg,
0, MP1_C2PMSG_90__CONTENT_MASK);
+ if (ret)
+ pr_err("No response from smu\n");
+
return cgs_read_register(hwmgr->device, reg);
}
@@ -102,14 +102,11 @@ static uint32_t vega10_wait_for_response(struct pp_hwmgr *hwmgr)
* @param msg the message to send.
* @return Always return 0.
*/
-int vega10_send_msg_to_smc_without_waiting(struct pp_hwmgr *hwmgr,
+static int vega10_send_msg_to_smc_without_waiting(struct pp_hwmgr *hwmgr,
uint16_t msg)
{
uint32_t reg;
- if (!vega10_is_smc_ram_running(hwmgr))
- return -EINVAL;
-
reg = soc15_get_register_offset(MP1_HWID, 0,
mmMP1_SMN_C2PMSG_66_BASE_IDX, mmMP1_SMN_C2PMSG_66);
cgs_write_register(hwmgr->device, reg, msg);
@@ -123,12 +120,10 @@ int vega10_send_msg_to_smc_without_waiting(struct pp_hwmgr *hwmgr,
* @param msg the message to send.
* @return Always return 0.
*/
-int vega10_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg)
+static int vega10_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg)
{
uint32_t reg;
-
- if (!vega10_is_smc_ram_running(hwmgr))
- return -EINVAL;
+ uint32_t ret;
vega10_wait_for_response(hwmgr);
@@ -138,8 +133,9 @@ int vega10_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg)
vega10_send_msg_to_smc_without_waiting(hwmgr, msg);
- if (vega10_wait_for_response(hwmgr) != 1)
- pr_err("Failed to send message: 0x%x\n", msg);
+ ret = vega10_wait_for_response(hwmgr);
+ if (ret != 1)
+ pr_err("Failed to send message: 0x%x, ret value: 0x%x\n", msg, ret);
return 0;
}
@@ -151,13 +147,11 @@ int vega10_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg)
* @param parameter: the parameter to send
* @return Always return 0.
*/
-int vega10_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr,
+static int vega10_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr,
uint16_t msg, uint32_t parameter)
{
uint32_t reg;
-
- if (!vega10_is_smc_ram_running(hwmgr))
- return -EINVAL;
+ uint32_t ret;
vega10_wait_for_response(hwmgr);
@@ -171,60 +165,27 @@ int vega10_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr,
vega10_send_msg_to_smc_without_waiting(hwmgr, msg);
- if (vega10_wait_for_response(hwmgr) != 1)
- pr_err("Failed to send message: 0x%x\n", msg);
+ ret = vega10_wait_for_response(hwmgr);
+ if (ret != 1)
+ pr_err("Failed message: 0x%x, input parameter: 0x%x, error code: 0x%x\n", msg, parameter, ret);
return 0;
}
-
-/*
- * Send a message to the SMC with parameter, do not wait for response
- * @param hwmgr: the address of the powerplay hardware manager.
- * @param msg: the message to send.
- * @param parameter: the parameter to send
- * @return The response that came from the SMC.
- */
-int vega10_send_msg_to_smc_with_parameter_without_waiting(
- struct pp_hwmgr *hwmgr, uint16_t msg, uint32_t parameter)
+static int vega10_get_argument(struct pp_hwmgr *hwmgr)
{
uint32_t reg;
reg = soc15_get_register_offset(MP1_HWID, 0,
mmMP1_SMN_C2PMSG_82_BASE_IDX, mmMP1_SMN_C2PMSG_82);
- cgs_write_register(hwmgr->device, reg, parameter);
- return vega10_send_msg_to_smc_without_waiting(hwmgr, msg);
-}
-
-/*
- * Retrieve an argument from SMC.
- * @param hwmgr the address of the powerplay hardware manager.
- * @param arg pointer to store the argument from SMC.
- * @return Always return 0.
- */
-int vega10_read_arg_from_smc(struct pp_hwmgr *hwmgr, uint32_t *arg)
-{
- uint32_t reg;
-
- reg = soc15_get_register_offset(MP1_HWID, 0,
- mmMP1_SMN_C2PMSG_82_BASE_IDX, mmMP1_SMN_C2PMSG_82);
-
- *arg = cgs_read_register(hwmgr->device, reg);
-
- return 0;
+ return cgs_read_register(hwmgr->device, reg);
}
-/*
- * Copy table from SMC into driver FB
- * @param hwmgr the address of the HW manager
- * @param table_id the driver's table ID to copy from
- */
-int vega10_copy_table_from_smc(struct pp_hwmgr *hwmgr,
+static int vega10_copy_table_from_smc(struct pp_hwmgr *hwmgr,
uint8_t *table, int16_t table_id)
{
- struct vega10_smumgr *priv =
- (struct vega10_smumgr *)(hwmgr->smu_backend);
+ struct vega10_smumgr *priv = hwmgr->smu_backend;
PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE,
"Invalid SMU Table ID!", return -EINVAL);
@@ -232,20 +193,15 @@ int vega10_copy_table_from_smc(struct pp_hwmgr *hwmgr,
"Invalid SMU Table version!", return -EINVAL);
PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0,
"Invalid SMU Table Length!", return -EINVAL);
- PP_ASSERT_WITH_CODE(vega10_send_msg_to_smc_with_parameter(hwmgr,
+ vega10_send_msg_to_smc_with_parameter(hwmgr,
PPSMC_MSG_SetDriverDramAddrHigh,
- priv->smu_tables.entry[table_id].table_addr_high) == 0,
- "[CopyTableFromSMC] Attempt to Set Dram Addr High Failed!", return -EINVAL);
- PP_ASSERT_WITH_CODE(vega10_send_msg_to_smc_with_parameter(hwmgr,
+ upper_32_bits(priv->smu_tables.entry[table_id].mc_addr));
+ vega10_send_msg_to_smc_with_parameter(hwmgr,
PPSMC_MSG_SetDriverDramAddrLow,
- priv->smu_tables.entry[table_id].table_addr_low) == 0,
- "[CopyTableFromSMC] Attempt to Set Dram Addr Low Failed!",
- return -EINVAL);
- PP_ASSERT_WITH_CODE(vega10_send_msg_to_smc_with_parameter(hwmgr,
+ lower_32_bits(priv->smu_tables.entry[table_id].mc_addr));
+ vega10_send_msg_to_smc_with_parameter(hwmgr,
PPSMC_MSG_TransferTableSmu2Dram,
- priv->smu_tables.entry[table_id].table_id) == 0,
- "[CopyTableFromSMC] Attempt to Transfer Table From SMU Failed!",
- return -EINVAL);
+ priv->smu_tables.entry[table_id].table_id);
memcpy(table, priv->smu_tables.entry[table_id].table,
priv->smu_tables.entry[table_id].size);
@@ -253,16 +209,10 @@ int vega10_copy_table_from_smc(struct pp_hwmgr *hwmgr,
return 0;
}
-/*
- * Copy table from Driver FB into SMC
- * @param hwmgr the address of the HW manager
- * @param table_id the table to copy from
- */
-int vega10_copy_table_to_smc(struct pp_hwmgr *hwmgr,
+static int vega10_copy_table_to_smc(struct pp_hwmgr *hwmgr,
uint8_t *table, int16_t table_id)
{
- struct vega10_smumgr *priv =
- (struct vega10_smumgr *)(hwmgr->smu_backend);
+ struct vega10_smumgr *priv = hwmgr->smu_backend;
PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE,
"Invalid SMU Table ID!", return -EINVAL);
@@ -274,81 +224,54 @@ int vega10_copy_table_to_smc(struct pp_hwmgr *hwmgr,
memcpy(priv->smu_tables.entry[table_id].table, table,
priv->smu_tables.entry[table_id].size);
- PP_ASSERT_WITH_CODE(vega10_send_msg_to_smc_with_parameter(hwmgr,
+ vega10_send_msg_to_smc_with_parameter(hwmgr,
PPSMC_MSG_SetDriverDramAddrHigh,
- priv->smu_tables.entry[table_id].table_addr_high) == 0,
- "[CopyTableToSMC] Attempt to Set Dram Addr High Failed!",
- return -EINVAL;);
- PP_ASSERT_WITH_CODE(vega10_send_msg_to_smc_with_parameter(hwmgr,
+ upper_32_bits(priv->smu_tables.entry[table_id].mc_addr));
+ vega10_send_msg_to_smc_with_parameter(hwmgr,
PPSMC_MSG_SetDriverDramAddrLow,
- priv->smu_tables.entry[table_id].table_addr_low) == 0,
- "[CopyTableToSMC] Attempt to Set Dram Addr Low Failed!",
- return -EINVAL);
- PP_ASSERT_WITH_CODE(vega10_send_msg_to_smc_with_parameter(hwmgr,
+ lower_32_bits(priv->smu_tables.entry[table_id].mc_addr));
+ vega10_send_msg_to_smc_with_parameter(hwmgr,
PPSMC_MSG_TransferTableDram2Smu,
- priv->smu_tables.entry[table_id].table_id) == 0,
- "[CopyTableToSMC] Attempt to Transfer Table To SMU Failed!",
- return -EINVAL);
+ priv->smu_tables.entry[table_id].table_id);
return 0;
}
-int vega10_save_vft_table(struct pp_hwmgr *hwmgr, uint8_t *avfs_table)
-{
- PP_ASSERT_WITH_CODE(avfs_table,
- "No access to SMC AVFS Table",
- return -EINVAL);
-
- return vega10_copy_table_from_smc(hwmgr, avfs_table, AVFSTABLE);
-}
-
-int vega10_restore_vft_table(struct pp_hwmgr *hwmgr, uint8_t *avfs_table)
+static int vega10_get_smc_features(struct pp_hwmgr *hwmgr,
+ uint32_t *features_enabled)
{
- PP_ASSERT_WITH_CODE(avfs_table,
- "No access to SMC AVFS Table",
- return -EINVAL);
-
- return vega10_copy_table_to_smc(hwmgr, avfs_table, AVFSTABLE);
-}
+ if (features_enabled == NULL)
+ return -EINVAL;
-int vega10_enable_smc_features(struct pp_hwmgr *hwmgr,
- bool enable, uint32_t feature_mask)
-{
- int msg = enable ? PPSMC_MSG_EnableSmuFeatures :
- PPSMC_MSG_DisableSmuFeatures;
+ vega10_send_msg_to_smc(hwmgr, PPSMC_MSG_GetEnabledSmuFeatures);
+ *features_enabled = vega10_get_argument(hwmgr);
- return vega10_send_msg_to_smc_with_parameter(hwmgr,
- msg, feature_mask);
+ return 0;
}
-int vega10_get_smc_features(struct pp_hwmgr *hwmgr,
- uint32_t *features_enabled)
+static bool vega10_is_dpm_running(struct pp_hwmgr *hwmgr)
{
- if (features_enabled == NULL)
- return -EINVAL;
+ uint32_t features_enabled = 0;
- if (!vega10_send_msg_to_smc(hwmgr,
- PPSMC_MSG_GetEnabledSmuFeatures)) {
- vega10_read_arg_from_smc(hwmgr, features_enabled);
- return 0;
- }
+ vega10_get_smc_features(hwmgr, &features_enabled);
- return -EINVAL;
+ if (features_enabled & SMC_DPM_FEATURES)
+ return true;
+ else
+ return false;
}
-int vega10_set_tools_address(struct pp_hwmgr *hwmgr)
+static int vega10_set_tools_address(struct pp_hwmgr *hwmgr)
{
- struct vega10_smumgr *priv =
- (struct vega10_smumgr *)(hwmgr->smu_backend);
+ struct vega10_smumgr *priv = hwmgr->smu_backend;
- if (priv->smu_tables.entry[TOOLSTABLE].table_addr_high ||
- priv->smu_tables.entry[TOOLSTABLE].table_addr_low) {
- if (!vega10_send_msg_to_smc_with_parameter(hwmgr,
+ if (priv->smu_tables.entry[TOOLSTABLE].mc_addr) {
+ vega10_send_msg_to_smc_with_parameter(hwmgr,
PPSMC_MSG_SetToolsDramAddrHigh,
- priv->smu_tables.entry[TOOLSTABLE].table_addr_high))
- vega10_send_msg_to_smc_with_parameter(hwmgr,
- PPSMC_MSG_SetToolsDramAddrLow,
- priv->smu_tables.entry[TOOLSTABLE].table_addr_low);
+ upper_32_bits(priv->smu_tables.entry[TOOLSTABLE].mc_addr));
+ vega10_send_msg_to_smc_with_parameter(hwmgr,
+ PPSMC_MSG_SetToolsDramAddrLow,
+ lower_32_bits(priv->smu_tables.entry[TOOLSTABLE].mc_addr));
}
return 0;
}
@@ -356,7 +279,7 @@ int vega10_set_tools_address(struct pp_hwmgr *hwmgr)
static int vega10_verify_smc_interface(struct pp_hwmgr *hwmgr)
{
uint32_t smc_driver_if_version;
- struct cgs_system_info sys_info = {0};
+ struct amdgpu_device *adev = hwmgr->adev;
uint32_t dev_id;
uint32_t rev_id;
@@ -364,17 +287,10 @@ static int vega10_verify_smc_interface(struct pp_hwmgr *hwmgr)
PPSMC_MSG_GetDriverIfVersion),
"Attempt to get SMC IF Version Number Failed!",
return -EINVAL);
- vega10_read_arg_from_smc(hwmgr, &smc_driver_if_version);
+ smc_driver_if_version = vega10_get_argument(hwmgr);
- 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);
- dev_id = (uint32_t)sys_info.value;
-
- sys_info.size = sizeof(struct cgs_system_info);
- sys_info.info_id = CGS_SYSTEM_INFO_PCIE_REV;
- cgs_query_system_info(hwmgr->device, &sys_info);
- rev_id = (uint32_t)sys_info.value;
+ dev_id = adev->pdev->device;
+ rev_id = adev->pdev->revision;
if (!((dev_id == 0x687f) &&
((rev_id == 0xc0) ||
@@ -393,14 +309,12 @@ static int vega10_verify_smc_interface(struct pp_hwmgr *hwmgr)
static int vega10_smu_init(struct pp_hwmgr *hwmgr)
{
struct vega10_smumgr *priv;
- uint64_t mc_addr;
- void *kaddr = NULL;
- unsigned long handle, tools_size;
+ unsigned long tools_size;
int ret;
struct cgs_firmware_info info = {0};
ret = cgs_get_firmware_info(hwmgr->device,
- smu7_convert_fw_type_to_cgs(UCODE_ID_SMU),
+ CGS_UCODE_ID_SMU,
&info);
if (ret || !info.kptr)
return -EINVAL;
@@ -413,166 +327,130 @@ static int vega10_smu_init(struct pp_hwmgr *hwmgr)
hwmgr->smu_backend = priv;
/* allocate space for pptable */
- smu_allocate_memory(hwmgr->device,
+ ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
sizeof(PPTable_t),
- CGS_GPU_MEM_TYPE__VISIBLE_CONTIG_FB,
PAGE_SIZE,
- &mc_addr,
- &kaddr,
- &handle);
-
- PP_ASSERT_WITH_CODE(kaddr,
- "[vega10_smu_init] Out of memory for pptable.",
- kfree(hwmgr->smu_backend);
- cgs_free_gpu_mem(hwmgr->device,
- (cgs_handle_t)handle);
- return -EINVAL);
+ AMDGPU_GEM_DOMAIN_VRAM,
+ &priv->smu_tables.entry[PPTABLE].handle,
+ &priv->smu_tables.entry[PPTABLE].mc_addr,
+ &priv->smu_tables.entry[PPTABLE].table);
+ if (ret)
+ goto free_backend;
priv->smu_tables.entry[PPTABLE].version = 0x01;
priv->smu_tables.entry[PPTABLE].size = sizeof(PPTable_t);
priv->smu_tables.entry[PPTABLE].table_id = TABLE_PPTABLE;
- priv->smu_tables.entry[PPTABLE].table_addr_high =
- smu_upper_32_bits(mc_addr);
- priv->smu_tables.entry[PPTABLE].table_addr_low =
- smu_lower_32_bits(mc_addr);
- priv->smu_tables.entry[PPTABLE].table = kaddr;
- priv->smu_tables.entry[PPTABLE].handle = handle;
/* allocate space for watermarks table */
- smu_allocate_memory(hwmgr->device,
+ ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
sizeof(Watermarks_t),
- CGS_GPU_MEM_TYPE__VISIBLE_CONTIG_FB,
PAGE_SIZE,
- &mc_addr,
- &kaddr,
- &handle);
-
- PP_ASSERT_WITH_CODE(kaddr,
- "[vega10_smu_init] Out of memory for wmtable.",
- kfree(hwmgr->smu_backend);
- cgs_free_gpu_mem(hwmgr->device,
- (cgs_handle_t)priv->smu_tables.entry[PPTABLE].handle);
- cgs_free_gpu_mem(hwmgr->device,
- (cgs_handle_t)handle);
- return -EINVAL);
+ AMDGPU_GEM_DOMAIN_VRAM,
+ &priv->smu_tables.entry[WMTABLE].handle,
+ &priv->smu_tables.entry[WMTABLE].mc_addr,
+ &priv->smu_tables.entry[WMTABLE].table);
+
+ if (ret)
+ goto err0;
priv->smu_tables.entry[WMTABLE].version = 0x01;
priv->smu_tables.entry[WMTABLE].size = sizeof(Watermarks_t);
priv->smu_tables.entry[WMTABLE].table_id = TABLE_WATERMARKS;
- priv->smu_tables.entry[WMTABLE].table_addr_high =
- smu_upper_32_bits(mc_addr);
- priv->smu_tables.entry[WMTABLE].table_addr_low =
- smu_lower_32_bits(mc_addr);
- priv->smu_tables.entry[WMTABLE].table = kaddr;
- priv->smu_tables.entry[WMTABLE].handle = handle;
/* allocate space for AVFS table */
- smu_allocate_memory(hwmgr->device,
+ ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
sizeof(AvfsTable_t),
- CGS_GPU_MEM_TYPE__VISIBLE_CONTIG_FB,
PAGE_SIZE,
- &mc_addr,
- &kaddr,
- &handle);
-
- PP_ASSERT_WITH_CODE(kaddr,
- "[vega10_smu_init] Out of memory for avfs table.",
- kfree(hwmgr->smu_backend);
- cgs_free_gpu_mem(hwmgr->device,
- (cgs_handle_t)priv->smu_tables.entry[PPTABLE].handle);
- cgs_free_gpu_mem(hwmgr->device,
- (cgs_handle_t)priv->smu_tables.entry[WMTABLE].handle);
- cgs_free_gpu_mem(hwmgr->device,
- (cgs_handle_t)handle);
- return -EINVAL);
+ AMDGPU_GEM_DOMAIN_VRAM,
+ &priv->smu_tables.entry[AVFSTABLE].handle,
+ &priv->smu_tables.entry[AVFSTABLE].mc_addr,
+ &priv->smu_tables.entry[AVFSTABLE].table);
+
+ if (ret)
+ goto err1;
priv->smu_tables.entry[AVFSTABLE].version = 0x01;
priv->smu_tables.entry[AVFSTABLE].size = sizeof(AvfsTable_t);
priv->smu_tables.entry[AVFSTABLE].table_id = TABLE_AVFS;
- priv->smu_tables.entry[AVFSTABLE].table_addr_high =
- smu_upper_32_bits(mc_addr);
- priv->smu_tables.entry[AVFSTABLE].table_addr_low =
- smu_lower_32_bits(mc_addr);
- priv->smu_tables.entry[AVFSTABLE].table = kaddr;
- priv->smu_tables.entry[AVFSTABLE].handle = handle;
tools_size = 0x19000;
if (tools_size) {
- smu_allocate_memory(hwmgr->device,
+ ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
tools_size,
- CGS_GPU_MEM_TYPE__VISIBLE_CONTIG_FB,
PAGE_SIZE,
- &mc_addr,
- &kaddr,
- &handle);
-
- if (kaddr) {
- priv->smu_tables.entry[TOOLSTABLE].version = 0x01;
- priv->smu_tables.entry[TOOLSTABLE].size = tools_size;
- priv->smu_tables.entry[TOOLSTABLE].table_id = TABLE_PMSTATUSLOG;
- priv->smu_tables.entry[TOOLSTABLE].table_addr_high =
- smu_upper_32_bits(mc_addr);
- priv->smu_tables.entry[TOOLSTABLE].table_addr_low =
- smu_lower_32_bits(mc_addr);
- priv->smu_tables.entry[TOOLSTABLE].table = kaddr;
- priv->smu_tables.entry[TOOLSTABLE].handle = handle;
- }
+ AMDGPU_GEM_DOMAIN_VRAM,
+ &priv->smu_tables.entry[TOOLSTABLE].handle,
+ &priv->smu_tables.entry[TOOLSTABLE].mc_addr,
+ &priv->smu_tables.entry[TOOLSTABLE].table);
+ if (ret)
+ goto err2;
+ priv->smu_tables.entry[TOOLSTABLE].version = 0x01;
+ priv->smu_tables.entry[TOOLSTABLE].size = tools_size;
+ priv->smu_tables.entry[TOOLSTABLE].table_id = TABLE_PMSTATUSLOG;
}
/* allocate space for AVFS Fuse table */
- smu_allocate_memory(hwmgr->device,
+ ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
sizeof(AvfsFuseOverride_t),
- CGS_GPU_MEM_TYPE__VISIBLE_CONTIG_FB,
PAGE_SIZE,
- &mc_addr,
- &kaddr,
- &handle);
-
- PP_ASSERT_WITH_CODE(kaddr,
- "[vega10_smu_init] Out of memory for avfs fuse table.",
- kfree(hwmgr->smu_backend);
- cgs_free_gpu_mem(hwmgr->device,
- (cgs_handle_t)priv->smu_tables.entry[PPTABLE].handle);
- cgs_free_gpu_mem(hwmgr->device,
- (cgs_handle_t)priv->smu_tables.entry[WMTABLE].handle);
- cgs_free_gpu_mem(hwmgr->device,
- (cgs_handle_t)priv->smu_tables.entry[AVFSTABLE].handle);
- cgs_free_gpu_mem(hwmgr->device,
- (cgs_handle_t)priv->smu_tables.entry[TOOLSTABLE].handle);
- cgs_free_gpu_mem(hwmgr->device,
- (cgs_handle_t)handle);
- return -EINVAL);
+ AMDGPU_GEM_DOMAIN_VRAM,
+ &priv->smu_tables.entry[AVFSFUSETABLE].handle,
+ &priv->smu_tables.entry[AVFSFUSETABLE].mc_addr,
+ &priv->smu_tables.entry[AVFSFUSETABLE].table);
+ if (ret)
+ goto err3;
priv->smu_tables.entry[AVFSFUSETABLE].version = 0x01;
priv->smu_tables.entry[AVFSFUSETABLE].size = sizeof(AvfsFuseOverride_t);
priv->smu_tables.entry[AVFSFUSETABLE].table_id = TABLE_AVFS_FUSE_OVERRIDE;
- priv->smu_tables.entry[AVFSFUSETABLE].table_addr_high =
- smu_upper_32_bits(mc_addr);
- priv->smu_tables.entry[AVFSFUSETABLE].table_addr_low =
- smu_lower_32_bits(mc_addr);
- priv->smu_tables.entry[AVFSFUSETABLE].table = kaddr;
- priv->smu_tables.entry[AVFSFUSETABLE].handle = handle;
+
return 0;
+
+err3:
+ if (priv->smu_tables.entry[TOOLSTABLE].table)
+ amdgpu_bo_free_kernel(&priv->smu_tables.entry[TOOLSTABLE].handle,
+ &priv->smu_tables.entry[TOOLSTABLE].mc_addr,
+ &priv->smu_tables.entry[TOOLSTABLE].table);
+err2:
+ amdgpu_bo_free_kernel(&priv->smu_tables.entry[AVFSTABLE].handle,
+ &priv->smu_tables.entry[AVFSTABLE].mc_addr,
+ &priv->smu_tables.entry[AVFSTABLE].table);
+err1:
+ amdgpu_bo_free_kernel(&priv->smu_tables.entry[WMTABLE].handle,
+ &priv->smu_tables.entry[WMTABLE].mc_addr,
+ &priv->smu_tables.entry[WMTABLE].table);
+err0:
+ amdgpu_bo_free_kernel(&priv->smu_tables.entry[PPTABLE].handle,
+ &priv->smu_tables.entry[PPTABLE].mc_addr,
+ &priv->smu_tables.entry[PPTABLE].table);
+free_backend:
+ kfree(hwmgr->smu_backend);
+
+ return -EINVAL;
}
static int vega10_smu_fini(struct pp_hwmgr *hwmgr)
{
- struct vega10_smumgr *priv =
- (struct vega10_smumgr *)(hwmgr->smu_backend);
+ struct vega10_smumgr *priv = hwmgr->smu_backend;
if (priv) {
- cgs_free_gpu_mem(hwmgr->device,
- (cgs_handle_t)priv->smu_tables.entry[PPTABLE].handle);
- cgs_free_gpu_mem(hwmgr->device,
- (cgs_handle_t)priv->smu_tables.entry[WMTABLE].handle);
- cgs_free_gpu_mem(hwmgr->device,
- (cgs_handle_t)priv->smu_tables.entry[AVFSTABLE].handle);
+ amdgpu_bo_free_kernel(&priv->smu_tables.entry[PPTABLE].handle,
+ &priv->smu_tables.entry[PPTABLE].mc_addr,
+ &priv->smu_tables.entry[PPTABLE].table);
+ amdgpu_bo_free_kernel(&priv->smu_tables.entry[WMTABLE].handle,
+ &priv->smu_tables.entry[WMTABLE].mc_addr,
+ &priv->smu_tables.entry[WMTABLE].table);
+ amdgpu_bo_free_kernel(&priv->smu_tables.entry[AVFSTABLE].handle,
+ &priv->smu_tables.entry[AVFSTABLE].mc_addr,
+ &priv->smu_tables.entry[AVFSTABLE].table);
if (priv->smu_tables.entry[TOOLSTABLE].table)
- cgs_free_gpu_mem(hwmgr->device,
- (cgs_handle_t)priv->smu_tables.entry[TOOLSTABLE].handle);
- cgs_free_gpu_mem(hwmgr->device,
- (cgs_handle_t)priv->smu_tables.entry[AVFSFUSETABLE].handle);
+ amdgpu_bo_free_kernel(&priv->smu_tables.entry[TOOLSTABLE].handle,
+ &priv->smu_tables.entry[TOOLSTABLE].mc_addr,
+ &priv->smu_tables.entry[TOOLSTABLE].table);
+ amdgpu_bo_free_kernel(&priv->smu_tables.entry[AVFSFUSETABLE].handle,
+ &priv->smu_tables.entry[AVFSFUSETABLE].mc_addr,
+ &priv->smu_tables.entry[AVFSFUSETABLE].table);
kfree(hwmgr->smu_backend);
hwmgr->smu_backend = NULL;
}
@@ -581,6 +459,9 @@ static int vega10_smu_fini(struct pp_hwmgr *hwmgr)
static int vega10_start_smu(struct pp_hwmgr *hwmgr)
{
+ if (!vega10_is_smc_ram_running(hwmgr))
+ return -EINVAL;
+
PP_ASSERT_WITH_CODE(!vega10_verify_smc_interface(hwmgr),
"Failed to verify SMC interface!",
return -EINVAL);
@@ -590,6 +471,18 @@ static int vega10_start_smu(struct pp_hwmgr *hwmgr)
return 0;
}
+static int vega10_smc_table_manager(struct pp_hwmgr *hwmgr, uint8_t *table, uint16_t table_id, bool rw)
+{
+ int ret;
+
+ if (rw)
+ ret = vega10_copy_table_from_smc(hwmgr, table, table_id);
+ else
+ ret = vega10_copy_table_to_smc(hwmgr, table, table_id);
+
+ return ret;
+}
+
const struct pp_smumgr_func vega10_smu_funcs = {
.smu_init = &vega10_smu_init,
.smu_fini = &vega10_smu_fini,
@@ -599,4 +492,7 @@ const struct pp_smumgr_func vega10_smu_funcs = {
.send_msg_to_smc_with_parameter = &vega10_send_msg_to_smc_with_parameter,
.download_pptable_settings = NULL,
.upload_pptable_settings = NULL,
+ .is_dpm_running = vega10_is_dpm_running,
+ .get_argument = vega10_get_argument,
+ .smc_table_manager = vega10_smc_table_manager,
};
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.h b/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.h
index 0695455b21b2..424e868bc768 100644
--- a/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.h
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.h
@@ -23,25 +23,15 @@
#ifndef _VEGA10_SMUMANAGER_H_
#define _VEGA10_SMUMANAGER_H_
-#include "vega10_hwmgr.h"
-
-enum smu_table_id {
- PPTABLE = 0,
- WMTABLE,
- AVFSTABLE,
- TOOLSTABLE,
- AVFSFUSETABLE,
- MAX_SMU_TABLE,
-};
+#define MAX_SMU_TABLE 5
struct smu_table_entry {
uint32_t version;
uint32_t size;
uint32_t table_id;
- uint32_t table_addr_high;
- uint32_t table_addr_low;
- uint8_t *table;
- unsigned long handle;
+ uint64_t mc_addr;
+ void *table;
+ struct amdgpu_bo *handle;
};
struct smu_table_array {
@@ -52,19 +42,6 @@ struct vega10_smumgr {
struct smu_table_array smu_tables;
};
-int vega10_read_arg_from_smc(struct pp_hwmgr *hwmgr, uint32_t *arg);
-int vega10_copy_table_from_smc(struct pp_hwmgr *hwmgr,
- uint8_t *table, int16_t table_id);
-int vega10_copy_table_to_smc(struct pp_hwmgr *hwmgr,
- uint8_t *table, int16_t table_id);
-int vega10_enable_smc_features(struct pp_hwmgr *hwmgr,
- bool enable, uint32_t feature_mask);
-int vega10_get_smc_features(struct pp_hwmgr *hwmgr,
- uint32_t *features_enabled);
-int vega10_save_vft_table(struct pp_hwmgr *hwmgr, uint8_t *avfs_table);
-int vega10_restore_vft_table(struct pp_hwmgr *hwmgr, uint8_t *avfs_table);
-
-int vega10_set_tools_address(struct pp_hwmgr *hwmgr);
#endif
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/vega12_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/vega12_smumgr.c
new file mode 100644
index 000000000000..55cd204c1789
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/vega12_smumgr.c
@@ -0,0 +1,561 @@
+/*
+ * 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 "smumgr.h"
+#include "vega12_inc.h"
+#include "pp_soc15.h"
+#include "vega12_smumgr.h"
+#include "vega12_ppsmc.h"
+#include "vega12/smu9_driver_if.h"
+
+#include "ppatomctrl.h"
+#include "pp_debug.h"
+#include "smu_ucode_xfer_vi.h"
+#include "smu7_smumgr.h"
+
+/* MP Apertures */
+#define MP0_Public 0x03800000
+#define MP0_SRAM 0x03900000
+#define MP1_Public 0x03b00000
+#define MP1_SRAM 0x03c00004
+
+#define smnMP1_FIRMWARE_FLAGS 0x3010028
+#define smnMP0_FW_INTF 0x3010104
+#define smnMP1_PUB_CTRL 0x3010b14
+
+static bool vega12_is_smc_ram_running(struct pp_hwmgr *hwmgr)
+{
+ uint32_t mp1_fw_flags, reg;
+
+ reg = soc15_get_register_offset(NBIF_HWID, 0,
+ mmPCIE_INDEX2_BASE_IDX, mmPCIE_INDEX2);
+
+ cgs_write_register(hwmgr->device, reg,
+ (MP1_Public | (smnMP1_FIRMWARE_FLAGS & 0xffffffff)));
+
+ reg = soc15_get_register_offset(NBIF_HWID, 0,
+ mmPCIE_DATA2_BASE_IDX, mmPCIE_DATA2);
+
+ mp1_fw_flags = cgs_read_register(hwmgr->device, reg);
+
+ if ((mp1_fw_flags & MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED_MASK) >>
+ MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED__SHIFT)
+ return true;
+
+ return false;
+}
+
+/*
+ * Check if SMC has responded to previous message.
+ *
+ * @param smumgr the address of the powerplay hardware manager.
+ * @return TRUE SMC has responded, FALSE otherwise.
+ */
+static uint32_t vega12_wait_for_response(struct pp_hwmgr *hwmgr)
+{
+ uint32_t reg;
+
+ reg = soc15_get_register_offset(MP1_HWID, 0,
+ mmMP1_SMN_C2PMSG_90_BASE_IDX, mmMP1_SMN_C2PMSG_90);
+
+ phm_wait_for_register_unequal(hwmgr, reg,
+ 0, MP1_C2PMSG_90__CONTENT_MASK);
+
+ return cgs_read_register(hwmgr->device, reg);
+}
+
+/*
+ * Send a message to the SMC, and do not wait for its response.
+ * @param smumgr the address of the powerplay hardware manager.
+ * @param msg the message to send.
+ * @return Always return 0.
+ */
+int vega12_send_msg_to_smc_without_waiting(struct pp_hwmgr *hwmgr,
+ uint16_t msg)
+{
+ uint32_t reg;
+
+ reg = soc15_get_register_offset(MP1_HWID, 0,
+ mmMP1_SMN_C2PMSG_66_BASE_IDX, mmMP1_SMN_C2PMSG_66);
+ cgs_write_register(hwmgr->device, reg, msg);
+
+ return 0;
+}
+
+/*
+ * Send a message to the SMC, and wait for its response.
+ * @param hwmgr the address of the powerplay hardware manager.
+ * @param msg the message to send.
+ * @return Always return 0.
+ */
+int vega12_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg)
+{
+ uint32_t reg;
+
+ vega12_wait_for_response(hwmgr);
+
+ reg = soc15_get_register_offset(MP1_HWID, 0,
+ mmMP1_SMN_C2PMSG_90_BASE_IDX, mmMP1_SMN_C2PMSG_90);
+ cgs_write_register(hwmgr->device, reg, 0);
+
+ vega12_send_msg_to_smc_without_waiting(hwmgr, msg);
+
+ if (vega12_wait_for_response(hwmgr) != 1)
+ pr_err("Failed to send message: 0x%x\n", msg);
+
+ return 0;
+}
+
+/*
+ * Send a message to the SMC with parameter
+ * @param hwmgr: the address of the powerplay hardware manager.
+ * @param msg: the message to send.
+ * @param parameter: the parameter to send
+ * @return Always return 0.
+ */
+int vega12_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr,
+ uint16_t msg, uint32_t parameter)
+{
+ uint32_t reg;
+
+ vega12_wait_for_response(hwmgr);
+
+ reg = soc15_get_register_offset(MP1_HWID, 0,
+ mmMP1_SMN_C2PMSG_90_BASE_IDX, mmMP1_SMN_C2PMSG_90);
+ cgs_write_register(hwmgr->device, reg, 0);
+
+ reg = soc15_get_register_offset(MP1_HWID, 0,
+ mmMP1_SMN_C2PMSG_82_BASE_IDX, mmMP1_SMN_C2PMSG_82);
+ cgs_write_register(hwmgr->device, reg, parameter);
+
+ vega12_send_msg_to_smc_without_waiting(hwmgr, msg);
+
+ if (vega12_wait_for_response(hwmgr) != 1)
+ pr_err("Failed to send message: 0x%x\n", msg);
+
+ return 0;
+}
+
+
+/*
+ * Send a message to the SMC with parameter, do not wait for response
+ * @param hwmgr: the address of the powerplay hardware manager.
+ * @param msg: the message to send.
+ * @param parameter: the parameter to send
+ * @return The response that came from the SMC.
+ */
+int vega12_send_msg_to_smc_with_parameter_without_waiting(
+ struct pp_hwmgr *hwmgr, uint16_t msg, uint32_t parameter)
+{
+ uint32_t reg;
+
+ reg = soc15_get_register_offset(MP1_HWID, 0,
+ mmMP1_SMN_C2PMSG_66_BASE_IDX, mmMP1_SMN_C2PMSG_66);
+ cgs_write_register(hwmgr->device, reg, parameter);
+
+ return vega12_send_msg_to_smc_without_waiting(hwmgr, msg);
+}
+
+/*
+ * Retrieve an argument from SMC.
+ * @param hwmgr the address of the powerplay hardware manager.
+ * @param arg pointer to store the argument from SMC.
+ * @return Always return 0.
+ */
+int vega12_read_arg_from_smc(struct pp_hwmgr *hwmgr, uint32_t *arg)
+{
+ uint32_t reg;
+
+ reg = soc15_get_register_offset(MP1_HWID, 0,
+ mmMP1_SMN_C2PMSG_82_BASE_IDX, mmMP1_SMN_C2PMSG_82);
+
+ *arg = cgs_read_register(hwmgr->device, reg);
+
+ return 0;
+}
+
+/*
+ * Copy table from SMC into driver FB
+ * @param hwmgr the address of the HW manager
+ * @param table_id the driver's table ID to copy from
+ */
+int vega12_copy_table_from_smc(struct pp_hwmgr *hwmgr,
+ uint8_t *table, int16_t table_id)
+{
+ struct vega12_smumgr *priv =
+ (struct vega12_smumgr *)(hwmgr->smu_backend);
+
+ PP_ASSERT_WITH_CODE(table_id < TABLE_COUNT,
+ "Invalid SMU Table ID!", return -EINVAL);
+ PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0,
+ "Invalid SMU Table version!", return -EINVAL);
+ PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0,
+ "Invalid SMU Table Length!", return -EINVAL);
+ PP_ASSERT_WITH_CODE(vega12_send_msg_to_smc_with_parameter(hwmgr,
+ PPSMC_MSG_SetDriverDramAddrHigh,
+ upper_32_bits(priv->smu_tables.entry[table_id].mc_addr)) == 0,
+ "[CopyTableFromSMC] Attempt to Set Dram Addr High Failed!", return -EINVAL);
+ PP_ASSERT_WITH_CODE(vega12_send_msg_to_smc_with_parameter(hwmgr,
+ PPSMC_MSG_SetDriverDramAddrLow,
+ lower_32_bits(priv->smu_tables.entry[table_id].mc_addr)) == 0,
+ "[CopyTableFromSMC] Attempt to Set Dram Addr Low Failed!",
+ return -EINVAL);
+ PP_ASSERT_WITH_CODE(vega12_send_msg_to_smc_with_parameter(hwmgr,
+ PPSMC_MSG_TransferTableSmu2Dram,
+ table_id) == 0,
+ "[CopyTableFromSMC] Attempt to Transfer Table From SMU Failed!",
+ return -EINVAL);
+
+ memcpy(table, priv->smu_tables.entry[table_id].table,
+ priv->smu_tables.entry[table_id].size);
+
+ return 0;
+}
+
+/*
+ * Copy table from Driver FB into SMC
+ * @param hwmgr the address of the HW manager
+ * @param table_id the table to copy from
+ */
+int vega12_copy_table_to_smc(struct pp_hwmgr *hwmgr,
+ uint8_t *table, int16_t table_id)
+{
+ struct vega12_smumgr *priv =
+ (struct vega12_smumgr *)(hwmgr->smu_backend);
+
+ PP_ASSERT_WITH_CODE(table_id < TABLE_COUNT,
+ "Invalid SMU Table ID!", return -EINVAL);
+ PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0,
+ "Invalid SMU Table version!", return -EINVAL);
+ PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0,
+ "Invalid SMU Table Length!", return -EINVAL);
+
+ memcpy(priv->smu_tables.entry[table_id].table, table,
+ priv->smu_tables.entry[table_id].size);
+
+ PP_ASSERT_WITH_CODE(vega12_send_msg_to_smc_with_parameter(hwmgr,
+ PPSMC_MSG_SetDriverDramAddrHigh,
+ upper_32_bits(priv->smu_tables.entry[table_id].mc_addr)) == 0,
+ "[CopyTableToSMC] Attempt to Set Dram Addr High Failed!",
+ return -EINVAL;);
+ PP_ASSERT_WITH_CODE(vega12_send_msg_to_smc_with_parameter(hwmgr,
+ PPSMC_MSG_SetDriverDramAddrLow,
+ lower_32_bits(priv->smu_tables.entry[table_id].mc_addr)) == 0,
+ "[CopyTableToSMC] Attempt to Set Dram Addr Low Failed!",
+ return -EINVAL);
+ PP_ASSERT_WITH_CODE(vega12_send_msg_to_smc_with_parameter(hwmgr,
+ PPSMC_MSG_TransferTableDram2Smu,
+ table_id) == 0,
+ "[CopyTableToSMC] Attempt to Transfer Table To SMU Failed!",
+ return -EINVAL);
+
+ return 0;
+}
+
+int vega12_enable_smc_features(struct pp_hwmgr *hwmgr,
+ bool enable, uint64_t feature_mask)
+{
+ uint32_t smu_features_low, smu_features_high;
+
+ smu_features_low = (uint32_t)((feature_mask & SMU_FEATURES_LOW_MASK) >> SMU_FEATURES_LOW_SHIFT);
+ smu_features_high = (uint32_t)((feature_mask & SMU_FEATURES_HIGH_MASK) >> SMU_FEATURES_HIGH_SHIFT);
+
+ if (enable) {
+ PP_ASSERT_WITH_CODE(vega12_send_msg_to_smc_with_parameter(hwmgr,
+ PPSMC_MSG_EnableSmuFeaturesLow, smu_features_low) == 0,
+ "[EnableDisableSMCFeatures] Attemp to enable SMU features Low failed!",
+ return -EINVAL);
+ PP_ASSERT_WITH_CODE(vega12_send_msg_to_smc_with_parameter(hwmgr,
+ PPSMC_MSG_EnableSmuFeaturesHigh, smu_features_high) == 0,
+ "[EnableDisableSMCFeatures] Attemp to enable SMU features High failed!",
+ return -EINVAL);
+ } else {
+ PP_ASSERT_WITH_CODE(vega12_send_msg_to_smc_with_parameter(hwmgr,
+ PPSMC_MSG_DisableSmuFeaturesLow, smu_features_low) == 0,
+ "[EnableDisableSMCFeatures] Attemp to disable SMU features Low failed!",
+ return -EINVAL);
+ PP_ASSERT_WITH_CODE(vega12_send_msg_to_smc_with_parameter(hwmgr,
+ PPSMC_MSG_DisableSmuFeaturesHigh, smu_features_high) == 0,
+ "[EnableDisableSMCFeatures] Attemp to disable SMU features High failed!",
+ return -EINVAL);
+ }
+
+ return 0;
+}
+
+int vega12_get_enabled_smc_features(struct pp_hwmgr *hwmgr,
+ uint64_t *features_enabled)
+{
+ uint32_t smc_features_low, smc_features_high;
+
+ if (features_enabled == NULL)
+ return -EINVAL;
+
+ PP_ASSERT_WITH_CODE(vega12_send_msg_to_smc(hwmgr,
+ PPSMC_MSG_GetEnabledSmuFeaturesLow) == 0,
+ "[GetEnabledSMCFeatures] Attemp to get SMU features Low failed!",
+ return -EINVAL);
+ PP_ASSERT_WITH_CODE(vega12_read_arg_from_smc(hwmgr,
+ &smc_features_low) == 0,
+ "[GetEnabledSMCFeatures] Attemp to read SMU features Low argument failed!",
+ return -EINVAL);
+ PP_ASSERT_WITH_CODE(vega12_send_msg_to_smc(hwmgr,
+ PPSMC_MSG_GetEnabledSmuFeaturesHigh) == 0,
+ "[GetEnabledSMCFeatures] Attemp to get SMU features High failed!",
+ return -EINVAL);
+ PP_ASSERT_WITH_CODE(vega12_read_arg_from_smc(hwmgr,
+ &smc_features_high) == 0,
+ "[GetEnabledSMCFeatures] Attemp to read SMU features High argument failed!",
+ return -EINVAL);
+
+ *features_enabled = ((((uint64_t)smc_features_low << SMU_FEATURES_LOW_SHIFT) & SMU_FEATURES_LOW_MASK) |
+ (((uint64_t)smc_features_high << SMU_FEATURES_HIGH_SHIFT) & SMU_FEATURES_HIGH_MASK));
+
+ return 0;
+}
+
+static bool vega12_is_dpm_running(struct pp_hwmgr *hwmgr)
+{
+ uint64_t features_enabled = 0;
+
+ vega12_get_enabled_smc_features(hwmgr, &features_enabled);
+
+ if (features_enabled & SMC_DPM_FEATURES)
+ return true;
+ else
+ return false;
+}
+
+static int vega12_set_tools_address(struct pp_hwmgr *hwmgr)
+{
+ struct vega12_smumgr *priv =
+ (struct vega12_smumgr *)(hwmgr->smu_backend);
+
+ if (priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr) {
+ if (!vega12_send_msg_to_smc_with_parameter(hwmgr,
+ PPSMC_MSG_SetToolsDramAddrHigh,
+ upper_32_bits(priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr)))
+ vega12_send_msg_to_smc_with_parameter(hwmgr,
+ PPSMC_MSG_SetToolsDramAddrLow,
+ lower_32_bits(priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr));
+ }
+ return 0;
+}
+
+#if 0 /* tentatively remove */
+static int vega12_verify_smc_interface(struct pp_hwmgr *hwmgr)
+{
+ uint32_t smc_driver_if_version;
+
+ PP_ASSERT_WITH_CODE(!vega12_send_msg_to_smc(hwmgr,
+ PPSMC_MSG_GetDriverIfVersion),
+ "Attempt to get SMC IF Version Number Failed!",
+ return -EINVAL);
+ vega12_read_arg_from_smc(hwmgr, &smc_driver_if_version);
+
+ if (smc_driver_if_version != SMU9_DRIVER_IF_VERSION) {
+ pr_err("Your firmware(0x%x) doesn't match \
+ SMU9_DRIVER_IF_VERSION(0x%x). \
+ Please update your firmware!\n",
+ smc_driver_if_version, SMU9_DRIVER_IF_VERSION);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+#endif
+
+static int vega12_smu_init(struct pp_hwmgr *hwmgr)
+{
+ struct vega12_smumgr *priv;
+ unsigned long tools_size;
+ struct cgs_firmware_info info = {0};
+ int ret;
+
+ ret = cgs_get_firmware_info(hwmgr->device,
+ smu7_convert_fw_type_to_cgs(UCODE_ID_SMU),
+ &info);
+ if (ret || !info.kptr)
+ return -EINVAL;
+
+ priv = kzalloc(sizeof(struct vega12_smumgr), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ hwmgr->smu_backend = priv;
+
+ /* allocate space for pptable */
+ ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
+ sizeof(PPTable_t),
+ PAGE_SIZE,
+ AMDGPU_GEM_DOMAIN_VRAM,
+ &priv->smu_tables.entry[TABLE_PPTABLE].handle,
+ &priv->smu_tables.entry[TABLE_PPTABLE].mc_addr,
+ &priv->smu_tables.entry[TABLE_PPTABLE].table);
+ if (ret)
+ goto free_backend;
+
+ priv->smu_tables.entry[TABLE_PPTABLE].version = 0x01;
+ priv->smu_tables.entry[TABLE_PPTABLE].size = sizeof(PPTable_t);
+
+ /* allocate space for watermarks table */
+ ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
+ sizeof(Watermarks_t),
+ PAGE_SIZE,
+ AMDGPU_GEM_DOMAIN_VRAM,
+ &priv->smu_tables.entry[TABLE_WATERMARKS].handle,
+ &priv->smu_tables.entry[TABLE_WATERMARKS].mc_addr,
+ &priv->smu_tables.entry[TABLE_WATERMARKS].table);
+
+ if (ret)
+ goto err0;
+
+ priv->smu_tables.entry[TABLE_WATERMARKS].version = 0x01;
+ priv->smu_tables.entry[TABLE_WATERMARKS].size = sizeof(Watermarks_t);
+
+ tools_size = 0x19000;
+ if (tools_size) {
+ ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
+ tools_size,
+ PAGE_SIZE,
+ AMDGPU_GEM_DOMAIN_VRAM,
+ &priv->smu_tables.entry[TABLE_PMSTATUSLOG].handle,
+ &priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr,
+ &priv->smu_tables.entry[TABLE_PMSTATUSLOG].table);
+ if (ret)
+ goto err1;
+
+ priv->smu_tables.entry[TABLE_PMSTATUSLOG].version = 0x01;
+ priv->smu_tables.entry[TABLE_PMSTATUSLOG].size = tools_size;
+ }
+
+ /* allocate space for AVFS Fuse table */
+ ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
+ sizeof(AvfsFuseOverride_t),
+ PAGE_SIZE,
+ AMDGPU_GEM_DOMAIN_VRAM,
+ &priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].handle,
+ &priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].mc_addr,
+ &priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].table);
+
+ if (ret)
+ goto err2;
+
+ priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].version = 0x01;
+ priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].size = sizeof(AvfsFuseOverride_t);
+
+ /* allocate space for OverDrive table */
+ ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
+ sizeof(OverDriveTable_t),
+ PAGE_SIZE,
+ AMDGPU_GEM_DOMAIN_VRAM,
+ &priv->smu_tables.entry[TABLE_OVERDRIVE].handle,
+ &priv->smu_tables.entry[TABLE_OVERDRIVE].mc_addr,
+ &priv->smu_tables.entry[TABLE_OVERDRIVE].table);
+ if (ret)
+ goto err3;
+
+ priv->smu_tables.entry[TABLE_OVERDRIVE].version = 0x01;
+ priv->smu_tables.entry[TABLE_OVERDRIVE].size = sizeof(OverDriveTable_t);
+
+ return 0;
+
+err3:
+ amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].handle,
+ &priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].mc_addr,
+ &priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].table);
+err2:
+ if (priv->smu_tables.entry[TABLE_PMSTATUSLOG].table)
+ amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_PMSTATUSLOG].handle,
+ &priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr,
+ &priv->smu_tables.entry[TABLE_PMSTATUSLOG].table);
+err1:
+ amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_WATERMARKS].handle,
+ &priv->smu_tables.entry[TABLE_WATERMARKS].mc_addr,
+ &priv->smu_tables.entry[TABLE_WATERMARKS].table);
+err0:
+ amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_PPTABLE].handle,
+ &priv->smu_tables.entry[TABLE_PPTABLE].mc_addr,
+ &priv->smu_tables.entry[TABLE_PPTABLE].table);
+free_backend:
+ kfree(hwmgr->smu_backend);
+
+ return -EINVAL;
+}
+
+static int vega12_smu_fini(struct pp_hwmgr *hwmgr)
+{
+ struct vega12_smumgr *priv =
+ (struct vega12_smumgr *)(hwmgr->smu_backend);
+
+ if (priv) {
+ amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_PPTABLE].handle,
+ &priv->smu_tables.entry[TABLE_PPTABLE].mc_addr,
+ &priv->smu_tables.entry[TABLE_PPTABLE].table);
+ amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_WATERMARKS].handle,
+ &priv->smu_tables.entry[TABLE_WATERMARKS].mc_addr,
+ &priv->smu_tables.entry[TABLE_WATERMARKS].table);
+ if (priv->smu_tables.entry[TABLE_PMSTATUSLOG].table)
+ amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_PMSTATUSLOG].handle,
+ &priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr,
+ &priv->smu_tables.entry[TABLE_PMSTATUSLOG].table);
+ amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].handle,
+ &priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].mc_addr,
+ &priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].table);
+ amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_OVERDRIVE].handle,
+ &priv->smu_tables.entry[TABLE_OVERDRIVE].mc_addr,
+ &priv->smu_tables.entry[TABLE_OVERDRIVE].table);
+ kfree(hwmgr->smu_backend);
+ hwmgr->smu_backend = NULL;
+ }
+ return 0;
+}
+
+static int vega12_start_smu(struct pp_hwmgr *hwmgr)
+{
+ PP_ASSERT_WITH_CODE(vega12_is_smc_ram_running(hwmgr),
+ "SMC is not running!",
+ return -EINVAL);
+
+#if 0 /* tentatively remove */
+ PP_ASSERT_WITH_CODE(!vega12_verify_smc_interface(hwmgr),
+ "Failed to verify SMC interface!",
+ return -EINVAL);
+#endif
+
+ vega12_set_tools_address(hwmgr);
+
+ return 0;
+}
+
+const struct pp_smumgr_func vega12_smu_funcs = {
+ .smu_init = &vega12_smu_init,
+ .smu_fini = &vega12_smu_fini,
+ .start_smu = &vega12_start_smu,
+ .request_smu_load_specific_fw = NULL,
+ .send_msg_to_smc = &vega12_send_msg_to_smc,
+ .send_msg_to_smc_with_parameter = &vega12_send_msg_to_smc_with_parameter,
+ .download_pptable_settings = NULL,
+ .upload_pptable_settings = NULL,
+ .is_dpm_running = vega12_is_dpm_running,
+};
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/vega12_smumgr.h b/drivers/gpu/drm/amd/powerplay/smumgr/vega12_smumgr.h
new file mode 100644
index 000000000000..2810d387b611
--- /dev/null
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/vega12_smumgr.h
@@ -0,0 +1,62 @@
+/*
+ * 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_SMUMANAGER_H_
+#define _VEGA12_SMUMANAGER_H_
+
+#include "hwmgr.h"
+#include "vega12/smu9_driver_if.h"
+#include "vega12_hwmgr.h"
+
+struct smu_table_entry {
+ uint32_t version;
+ uint32_t size;
+ uint64_t mc_addr;
+ void *table;
+ struct amdgpu_bo *handle;
+};
+
+struct smu_table_array {
+ struct smu_table_entry entry[TABLE_COUNT];
+};
+
+struct vega12_smumgr {
+ struct smu_table_array smu_tables;
+};
+
+#define SMU_FEATURES_LOW_MASK 0x00000000FFFFFFFF
+#define SMU_FEATURES_LOW_SHIFT 0
+#define SMU_FEATURES_HIGH_MASK 0xFFFFFFFF00000000
+#define SMU_FEATURES_HIGH_SHIFT 32
+
+int vega12_read_arg_from_smc(struct pp_hwmgr *hwmgr, uint32_t *arg);
+int vega12_copy_table_from_smc(struct pp_hwmgr *hwmgr,
+ uint8_t *table, int16_t table_id);
+int vega12_copy_table_to_smc(struct pp_hwmgr *hwmgr,
+ uint8_t *table, int16_t table_id);
+int vega12_enable_smc_features(struct pp_hwmgr *hwmgr,
+ bool enable, uint64_t feature_mask);
+int vega12_get_enabled_smc_features(struct pp_hwmgr *hwmgr,
+ uint64_t *features_enabled);
+
+#endif
+