diff options
author | Dave Airlie <airlied@redhat.com> | 2016-07-08 13:42:41 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2016-07-08 13:42:41 +1000 |
commit | 6f6e68b383314ab10189f983fead55437c149f32 (patch) | |
tree | a9254f00bb2053aa567981c8979c9713d648346c /drivers/gpu/drm/amd/powerplay | |
parent | b33e07731c13f2a9ec5c345b8542cae5adf74235 (diff) | |
parent | b1814a1def0564a2a1d3be7fa5bf7243ff899a28 (diff) |
Merge branch 'drm-next-4.8' of git://people.freedesktop.org/~agd5f/linux into drm-next
This is the main 4.8 pull for radeon and amdgpu. Sorry for the delay,
I meant to send this out last week, but I was moving house. Lots of
changes here:
- ATPX improvements for better dGPU power control on PX systems
- New power features for CZ/BR/ST
- Pipelined BO moves and evictions in TTM
- GPU scheduler improvements
- GPU reset improvements
- Overclocking on dGPUs with amdgpu
- Lots of code cleanup
- Bug fixes
* 'drm-next-4.8' of git://people.freedesktop.org/~agd5f/linux: (191 commits)
drm/amd/powerplay: don't add invalid voltage.
drm/amdgpu: add read/write function for GC CAC programming
drm/amd/powerplay: add definitions related to di/dt feature for fiji and polaris.
drm/amd/powerplay: add shared definitions for di/dt feature.
drm/amdgpu: remove gfx8 registers that vary between asics
drm/amd/powerplay: add mvdd dpm support.
drm/amdgpu: get number of shade engine by cgs interface.
drm/amdgpu: remove more of the ring backup code
drm/amd/powerplay: Unify family defines
drm/amdgpu: clean up ring_backup code, no need more
drm/amdgpu: ib test first after gpu reset
drm/amdgpu: recovery hw jobs when gpu reset V3
drm/amdgpu: abstract amdgpu_vm_is_gpu_reset
drm/amdgpu: add a bool to specify if needing vm flush V2
drm/amdgpu: add amd_sched_job_recovery
drm/amdgpu: force completion for gpu reset
drm/amdgpu: block ttm first before parking scheduler
drm/amd: add amd_sched_hw_job_reset
drm/amd: add parent for sched fence
drm/amdgpu: remove evict vram
...
Diffstat (limited to 'drivers/gpu/drm/amd/powerplay')
24 files changed, 1106 insertions, 250 deletions
diff --git a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c index e629f8a9fe93..f9e03ad0baa2 100644 --- a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c +++ b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c @@ -536,6 +536,10 @@ int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_event event_id, void *input, case AMD_PP_EVENT_COMPLETE_INIT: ret = pem_handle_event(pp_handle->eventmgr, event_id, &data); break; + case AMD_PP_EVENT_READJUST_POWER_STATE: + pp_handle->hwmgr->current_ps = pp_handle->hwmgr->boot_ps; + ret = pem_handle_event(pp_handle->eventmgr, event_id, &data); + break; default: break; } @@ -740,12 +744,12 @@ static int pp_dpm_get_pp_table(void *handle, char **table) PP_CHECK_HW(hwmgr); - if (hwmgr->hwmgr_func->get_pp_table == NULL) { - printk(KERN_INFO "%s was not implemented.\n", __func__); - return 0; - } + if (!hwmgr->soft_pp_table) + return -EINVAL; + + *table = (char *)hwmgr->soft_pp_table; - return hwmgr->hwmgr_func->get_pp_table(hwmgr, table); + return hwmgr->soft_pp_table_size; } static int pp_dpm_set_pp_table(void *handle, const char *buf, size_t size) @@ -759,12 +763,23 @@ static int pp_dpm_set_pp_table(void *handle, const char *buf, size_t size) PP_CHECK_HW(hwmgr); - if (hwmgr->hwmgr_func->set_pp_table == NULL) { - printk(KERN_INFO "%s was not implemented.\n", __func__); - return 0; + if (!hwmgr->hardcode_pp_table) { + hwmgr->hardcode_pp_table = + kzalloc(hwmgr->soft_pp_table_size, GFP_KERNEL); + + if (!hwmgr->hardcode_pp_table) + return -ENOMEM; + + /* to avoid powerplay crash when hardcode pptable is empty */ + memcpy(hwmgr->hardcode_pp_table, hwmgr->soft_pp_table, + hwmgr->soft_pp_table_size); } - return hwmgr->hwmgr_func->set_pp_table(hwmgr, buf, size); + memcpy(hwmgr->hardcode_pp_table, buf, size); + + hwmgr->soft_pp_table = hwmgr->hardcode_pp_table; + + return amd_powerplay_reset(handle); } static int pp_dpm_force_clock_level(void *handle, @@ -806,6 +821,82 @@ static int pp_dpm_print_clock_levels(void *handle, return hwmgr->hwmgr_func->print_clock_levels(hwmgr, type, buf); } +static int pp_dpm_get_sclk_od(void *handle) +{ + struct pp_hwmgr *hwmgr; + + if (!handle) + return -EINVAL; + + hwmgr = ((struct pp_instance *)handle)->hwmgr; + + PP_CHECK_HW(hwmgr); + + if (hwmgr->hwmgr_func->get_sclk_od == NULL) { + printk(KERN_INFO "%s was not implemented.\n", __func__); + return 0; + } + + return hwmgr->hwmgr_func->get_sclk_od(hwmgr); +} + +static int pp_dpm_set_sclk_od(void *handle, uint32_t value) +{ + struct pp_hwmgr *hwmgr; + + if (!handle) + return -EINVAL; + + hwmgr = ((struct pp_instance *)handle)->hwmgr; + + PP_CHECK_HW(hwmgr); + + if (hwmgr->hwmgr_func->set_sclk_od == NULL) { + printk(KERN_INFO "%s was not implemented.\n", __func__); + return 0; + } + + return hwmgr->hwmgr_func->set_sclk_od(hwmgr, value); +} + +static int pp_dpm_get_mclk_od(void *handle) +{ + struct pp_hwmgr *hwmgr; + + if (!handle) + return -EINVAL; + + hwmgr = ((struct pp_instance *)handle)->hwmgr; + + PP_CHECK_HW(hwmgr); + + if (hwmgr->hwmgr_func->get_mclk_od == NULL) { + printk(KERN_INFO "%s was not implemented.\n", __func__); + return 0; + } + + return hwmgr->hwmgr_func->get_mclk_od(hwmgr); +} + +static int pp_dpm_set_mclk_od(void *handle, uint32_t value) +{ + struct pp_hwmgr *hwmgr; + + if (!handle) + return -EINVAL; + + hwmgr = ((struct pp_instance *)handle)->hwmgr; + + PP_CHECK_HW(hwmgr); + + if (hwmgr->hwmgr_func->set_mclk_od == NULL) { + printk(KERN_INFO "%s was not implemented.\n", __func__); + return 0; + } + + return hwmgr->hwmgr_func->set_mclk_od(hwmgr, value); +} + const struct amd_powerplay_funcs pp_dpm_funcs = { .get_temperature = pp_dpm_get_temperature, .load_firmware = pp_dpm_load_fw, @@ -828,6 +919,10 @@ const struct amd_powerplay_funcs pp_dpm_funcs = { .set_pp_table = pp_dpm_set_pp_table, .force_clock_level = pp_dpm_force_clock_level, .print_clock_levels = pp_dpm_print_clock_levels, + .get_sclk_od = pp_dpm_get_sclk_od, + .set_sclk_od = pp_dpm_set_sclk_od, + .get_mclk_od = pp_dpm_get_mclk_od, + .set_mclk_od = pp_dpm_set_mclk_od, }; static int amd_pp_instance_init(struct amd_pp_init *pp_init, @@ -909,6 +1004,44 @@ int amd_powerplay_fini(void *handle) return 0; } +int amd_powerplay_reset(void *handle) +{ + struct pp_instance *instance = (struct pp_instance *)handle; + struct pp_eventmgr *eventmgr; + struct pem_event_data event_data = { {0} }; + int ret; + + if (instance == NULL) + return -EINVAL; + + eventmgr = instance->eventmgr; + if (!eventmgr || !eventmgr->pp_eventmgr_fini) + return -EINVAL; + + eventmgr->pp_eventmgr_fini(eventmgr); + + ret = pp_sw_fini(handle); + if (ret) + return ret; + + kfree(instance->hwmgr->ps); + + ret = pp_sw_init(handle); + if (ret) + return ret; + + hw_init_power_state_table(instance->hwmgr); + + if (eventmgr == NULL || eventmgr->pp_eventmgr_init == NULL) + return -EINVAL; + + ret = eventmgr->pp_eventmgr_init(eventmgr); + if (ret) + return ret; + + return pem_handle_event(eventmgr, AMD_PP_EVENT_COMPLETE_INIT, &event_data); +} + /* export this function to DAL */ int amd_powerplay_display_configuration_change(void *handle, diff --git a/drivers/gpu/drm/amd/powerplay/eventmgr/eventtasks.c b/drivers/gpu/drm/amd/powerplay/eventmgr/eventtasks.c index 5cd123472db4..b6f45fd01fa6 100644 --- a/drivers/gpu/drm/amd/powerplay/eventmgr/eventtasks.c +++ b/drivers/gpu/drm/amd/powerplay/eventmgr/eventtasks.c @@ -132,8 +132,7 @@ int pem_task_enable_dynamic_state_management(struct pp_eventmgr *eventmgr, struc int pem_task_disable_dynamic_state_management(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) { - /* TODO */ - return 0; + return phm_disable_dynamic_state_management(eventmgr->hwmgr); } int pem_task_enable_clock_power_gatings_tasks(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.c b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.c index 436fc16dabb6..2da548f6337e 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.c @@ -206,7 +206,7 @@ int cz_dpm_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate) AMD_IP_BLOCK_TYPE_VCE, AMD_PG_STATE_GATE); cz_enable_disable_vce_dpm(hwmgr, false); - /* TODO: to figure out why vce can't be poweroff*/ + cz_dpm_powerdown_vce(hwmgr); cz_hwmgr->vce_power_gated = true; } else { cz_dpm_powerup_vce(hwmgr); @@ -225,6 +225,7 @@ int cz_dpm_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate) } } } else { + cz_hwmgr->vce_power_gated = bgate; cz_dpm_update_vce_dpm(hwmgr); cz_enable_disable_vce_dpm(hwmgr, !bgate); return 0; diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c index 1f14c477d15d..9bf622e123b6 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c @@ -1180,6 +1180,13 @@ static int cz_apply_state_adjust_rules(struct pp_hwmgr *hwmgr, static int cz_hwmgr_backend_init(struct pp_hwmgr *hwmgr) { int result = 0; + struct cz_hwmgr *data; + + data = kzalloc(sizeof(struct cz_hwmgr), GFP_KERNEL); + if (data == NULL) + return -ENOMEM; + + hwmgr->backend = data; result = cz_initialize_dpm_defaults(hwmgr); if (result != 0) { @@ -1909,15 +1916,7 @@ static const struct pp_hwmgr_func cz_hwmgr_funcs = { int cz_hwmgr_init(struct pp_hwmgr *hwmgr) { - struct cz_hwmgr *cz_hwmgr; - int ret = 0; - - cz_hwmgr = kzalloc(sizeof(struct cz_hwmgr), GFP_KERNEL); - if (cz_hwmgr == NULL) - return -ENOMEM; - - hwmgr->backend = cz_hwmgr; hwmgr->hwmgr_func = &cz_hwmgr_funcs; hwmgr->pptable_func = &pptable_funcs; - return ret; + return 0; } diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.c index 92912ab20944..744aa886a2be 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.c @@ -581,25 +581,24 @@ static int fiji_patch_boot_state(struct pp_hwmgr *hwmgr, static int fiji_hwmgr_backend_fini(struct pp_hwmgr *hwmgr) { - struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); - - if (data->soft_pp_table) { - kfree(data->soft_pp_table); - data->soft_pp_table = NULL; - } - return phm_hwmgr_backend_fini(hwmgr); } static int fiji_hwmgr_backend_init(struct pp_hwmgr *hwmgr) { - struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + struct fiji_hwmgr *data; uint32_t i; struct phm_ppt_v1_information *table_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); bool stay_in_boot; int result; + data = kzalloc(sizeof(struct fiji_hwmgr), GFP_KERNEL); + if (data == NULL) + return -ENOMEM; + + hwmgr->backend = data; + data->dll_default_on = false; data->sram_end = SMC_RAM_END; @@ -734,7 +733,7 @@ static int fiji_hwmgr_backend_init(struct pp_hwmgr *hwmgr) sys_info.info_id = CGS_SYSTEM_INFO_PCIE_GEN_INFO; result = cgs_query_system_info(hwmgr->device, &sys_info); if (result) - data->pcie_gen_cap = 0x30007; + data->pcie_gen_cap = AMDGPU_DEFAULT_PCIE_GEN_MASK; else data->pcie_gen_cap = (uint32_t)sys_info.value; if (data->pcie_gen_cap & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3) @@ -743,7 +742,7 @@ static int fiji_hwmgr_backend_init(struct pp_hwmgr *hwmgr) sys_info.info_id = CGS_SYSTEM_INFO_PCIE_MLW; result = cgs_query_system_info(hwmgr->device, &sys_info); if (result) - data->pcie_lane_cap = 0x2f0000; + data->pcie_lane_cap = AMDGPU_DEFAULT_PCIE_MLW_MASK; else data->pcie_lane_cap = (uint32_t)sys_info.value; } else { @@ -1236,6 +1235,34 @@ static int fiji_program_voting_clients(struct pp_hwmgr *hwmgr) return 0; } +static int fiji_clear_voting_clients(struct pp_hwmgr *hwmgr) +{ + /* Reset voting clients before disabling DPM */ + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + SCLK_PWRMGT_CNTL, RESET_SCLK_CNT, 1); + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + SCLK_PWRMGT_CNTL, RESET_BUSY_CNT, 1); + + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_FREQ_TRAN_VOTING_0, 0); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_FREQ_TRAN_VOTING_1, 0); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_FREQ_TRAN_VOTING_2, 0); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_FREQ_TRAN_VOTING_3, 0); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_FREQ_TRAN_VOTING_4, 0); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_FREQ_TRAN_VOTING_5, 0); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_FREQ_TRAN_VOTING_6, 0); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_FREQ_TRAN_VOTING_7, 0); + + return 0; +} + /** * Get the location of various tables inside the FW image. * @@ -1363,6 +1390,17 @@ static int fiji_copy_and_switch_arb_sets(struct pp_hwmgr *hwmgr, } /** +* Call SMC to reset S0/S1 to S1 and Reset SMIO to initial value +* +* @param hwmgr the address of the powerplay hardware manager. +* @return if success then 0; +*/ +static int fiji_reset_to_default(struct pp_hwmgr *hwmgr) +{ + return smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_ResetToDefaults); +} + +/** * Initial switch from ARB F0->F1 * * @param hwmgr the address of the powerplay hardware manager. @@ -1375,6 +1413,21 @@ static int fiji_initial_switch_from_arbf0_to_f1(struct pp_hwmgr *hwmgr) MC_CG_ARB_FREQ_F0, MC_CG_ARB_FREQ_F1); } +static int fiji_force_switch_to_arbf0(struct pp_hwmgr *hwmgr) +{ + uint32_t tmp; + + tmp = (cgs_read_ind_register(hwmgr->device, + CGS_IND_REG__SMC, ixSMC_SCRATCH9) & + 0x0000ff00) >> 8; + + if (tmp == MC_CG_ARB_FREQ_F0) + return 0; + + return fiji_copy_and_switch_arb_sets(hwmgr, + tmp, MC_CG_ARB_FREQ_F0); +} + static int fiji_reset_single_dpm_table(struct pp_hwmgr *hwmgr, struct fiji_single_dpm_table *dpm_table, uint32_t count) { @@ -3177,6 +3230,17 @@ static int fiji_enable_ulv(struct pp_hwmgr *hwmgr) return 0; } +static int fiji_disable_ulv(struct pp_hwmgr *hwmgr) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + struct fiji_ulv_parm *ulv = &(data->ulv); + + if (ulv->ulv_supported) + return smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_DisableULV); + + return 0; +} + static int fiji_enable_deep_sleep_master_switch(struct pp_hwmgr *hwmgr) { if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, @@ -3197,6 +3261,21 @@ static int fiji_enable_deep_sleep_master_switch(struct pp_hwmgr *hwmgr) return 0; } +static int fiji_disable_deep_sleep_master_switch(struct pp_hwmgr *hwmgr) +{ + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SclkDeepSleep)) { + if (smum_send_msg_to_smc(hwmgr->smumgr, + PPSMC_MSG_MASTER_DeepSleep_OFF)) { + PP_ASSERT_WITH_CODE(false, + "Attempt to disable Master Deep Sleep switch failed!", + return -1); + } + } + + return 0; +} + static int fiji_enable_sclk_mclk_dpm(struct pp_hwmgr *hwmgr) { struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); @@ -3357,6 +3436,70 @@ static int fiji_start_dpm(struct pp_hwmgr *hwmgr) return 0; } +static int fiji_disable_sclk_mclk_dpm(struct pp_hwmgr *hwmgr) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + + /* disable SCLK dpm */ + if (!data->sclk_dpm_key_disabled) + PP_ASSERT_WITH_CODE( + (smum_send_msg_to_smc(hwmgr->smumgr, + PPSMC_MSG_DPM_Disable) == 0), + "Failed to disable SCLK DPM!", + return -1); + + /* disable MCLK dpm */ + if (!data->mclk_dpm_key_disabled) { + PP_ASSERT_WITH_CODE( + (smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + PPSMC_MSG_MCLKDPM_SetEnabledMask, 1) == 0), + "Failed to force MCLK DPM0!", + return -1); + + PP_ASSERT_WITH_CODE( + (smum_send_msg_to_smc(hwmgr->smumgr, + PPSMC_MSG_MCLKDPM_Disable) == 0), + "Failed to disable MCLK DPM!", + return -1); + } + + return 0; +} + +static int fiji_stop_dpm(struct pp_hwmgr *hwmgr) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + + /* disable general power management */ + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, GENERAL_PWRMGT, + GLOBAL_PWRMGT_EN, 0); + /* disable sclk deep sleep */ + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SCLK_PWRMGT_CNTL, + DYNAMIC_PM_EN, 0); + + /* disable PCIE dpm */ + if (!data->pcie_dpm_key_disabled) { + PP_ASSERT_WITH_CODE( + (smum_send_msg_to_smc(hwmgr->smumgr, + PPSMC_MSG_PCIeDPM_Disable) == 0), + "Failed to disable pcie DPM during DPM Stop Function!", + return -1); + } + + if (fiji_disable_sclk_mclk_dpm(hwmgr)) { + printk(KERN_ERR "Failed to disable Sclk DPM and Mclk DPM!"); + return -1; + } + + PP_ASSERT_WITH_CODE( + (smum_send_msg_to_smc(hwmgr->smumgr, + PPSMC_MSG_Voltage_Cntl_Disable) == 0), + "Failed to disable voltage DPM during DPM Stop Function!", + return -1); + + return 0; +} + static void fiji_set_dpm_event_sources(struct pp_hwmgr *hwmgr, uint32_t sources) { @@ -3415,6 +3558,23 @@ static int fiji_enable_thermal_auto_throttle(struct pp_hwmgr *hwmgr) return fiji_enable_auto_throttle_source(hwmgr, PHM_AutoThrottleSource_Thermal); } +static int fiji_disable_auto_throttle_source(struct pp_hwmgr *hwmgr, + PHM_AutoThrottleSource source) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + + if (data->active_auto_throttle_sources & (1 << source)) { + data->active_auto_throttle_sources &= ~(1 << source); + fiji_set_dpm_event_sources(hwmgr, data->active_auto_throttle_sources); + } + return 0; +} + +static int fiji_disable_thermal_auto_throttle(struct pp_hwmgr *hwmgr) +{ + return fiji_disable_auto_throttle_source(hwmgr, PHM_AutoThrottleSource_Thermal); +} + static int fiji_enable_dpm_tasks(struct pp_hwmgr *hwmgr) { int tmp_result, result = 0; @@ -3529,6 +3689,64 @@ static int fiji_enable_dpm_tasks(struct pp_hwmgr *hwmgr) return result; } +static int fiji_disable_dpm_tasks(struct pp_hwmgr *hwmgr) +{ + int tmp_result, result = 0; + + tmp_result = (fiji_is_dpm_running(hwmgr)) ? 0 : -1; + PP_ASSERT_WITH_CODE(tmp_result == 0, + "DPM is not running right now, no need to disable DPM!", + return 0); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ThermalController)) + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + GENERAL_PWRMGT, THERMAL_PROTECTION_DIS, 1); + + tmp_result = fiji_disable_power_containment(hwmgr); + PP_ASSERT_WITH_CODE((tmp_result == 0), + "Failed to disable power containment!", result = tmp_result); + + tmp_result = fiji_disable_smc_cac(hwmgr); + PP_ASSERT_WITH_CODE((tmp_result == 0), + "Failed to disable SMC CAC!", result = tmp_result); + + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_SPLL_SPREAD_SPECTRUM, SSEN, 0); + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + GENERAL_PWRMGT, DYN_SPREAD_SPECTRUM_EN, 0); + + tmp_result = fiji_disable_thermal_auto_throttle(hwmgr); + PP_ASSERT_WITH_CODE((tmp_result == 0), + "Failed to disable thermal auto throttle!", result = tmp_result); + + tmp_result = fiji_stop_dpm(hwmgr); + PP_ASSERT_WITH_CODE((tmp_result == 0), + "Failed to stop DPM!", result = tmp_result); + + tmp_result = fiji_disable_deep_sleep_master_switch(hwmgr); + PP_ASSERT_WITH_CODE((tmp_result == 0), + "Failed to disable deep sleep master switch!", result = tmp_result); + + tmp_result = fiji_disable_ulv(hwmgr); + PP_ASSERT_WITH_CODE((tmp_result == 0), + "Failed to disable ULV!", result = tmp_result); + + tmp_result = fiji_clear_voting_clients(hwmgr); + PP_ASSERT_WITH_CODE((tmp_result == 0), + "Failed to clear voting clients!", result = tmp_result); + + tmp_result = fiji_reset_to_default(hwmgr); + PP_ASSERT_WITH_CODE((tmp_result == 0), + "Failed to reset to default!", result = tmp_result); + + tmp_result = fiji_force_switch_to_arbf0(hwmgr); + PP_ASSERT_WITH_CODE((tmp_result == 0), + "Failed to force to switch arbf0!", result = tmp_result); + + return result; +} + static int fiji_force_dpm_highest(struct pp_hwmgr *hwmgr) { struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); @@ -5071,42 +5289,6 @@ static int fiji_get_fan_control_mode(struct pp_hwmgr *hwmgr) CG_FDO_CTRL2, FDO_PWM_MODE); } -static int fiji_get_pp_table(struct pp_hwmgr *hwmgr, char **table) -{ - struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); - - if (!data->soft_pp_table) { - data->soft_pp_table = kmemdup(hwmgr->soft_pp_table, - hwmgr->soft_pp_table_size, - GFP_KERNEL); - if (!data->soft_pp_table) - return -ENOMEM; - } - - *table = (char *)&data->soft_pp_table; - - return hwmgr->soft_pp_table_size; -} - -static int fiji_set_pp_table(struct pp_hwmgr *hwmgr, const char *buf, size_t size) -{ - struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); - - if (!data->soft_pp_table) { - data->soft_pp_table = kzalloc(hwmgr->soft_pp_table_size, GFP_KERNEL); - if (!data->soft_pp_table) - return -ENOMEM; - } - - memcpy(data->soft_pp_table, buf, size); - - hwmgr->soft_pp_table = data->soft_pp_table; - - /* TODO: re-init powerplay to implement modified pptable */ - - return 0; -} - static int fiji_force_clock_level(struct pp_hwmgr *hwmgr, enum pp_clock_type type, uint32_t mask) { @@ -5276,12 +5458,96 @@ bool fiji_check_smc_update_required_for_display_configuration(struct pp_hwmgr *h return is_update_required; } +static int fiji_get_sclk_od(struct pp_hwmgr *hwmgr) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + struct fiji_single_dpm_table *sclk_table = &(data->dpm_table.sclk_table); + struct fiji_single_dpm_table *golden_sclk_table = + &(data->golden_dpm_table.sclk_table); + int value; + + value = (sclk_table->dpm_levels[sclk_table->count - 1].value - + golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value) * + 100 / + golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value; + + return value; +} + +static int fiji_set_sclk_od(struct pp_hwmgr *hwmgr, uint32_t value) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + struct fiji_single_dpm_table *golden_sclk_table = + &(data->golden_dpm_table.sclk_table); + struct pp_power_state *ps; + struct fiji_power_state *fiji_ps; + + if (value > 20) + value = 20; + + ps = hwmgr->request_ps; + + if (ps == NULL) + return -EINVAL; + + fiji_ps = cast_phw_fiji_power_state(&ps->hardware); + + fiji_ps->performance_levels[fiji_ps->performance_level_count - 1].engine_clock = + golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value * + value / 100 + + golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value; + + return 0; +} + +static int fiji_get_mclk_od(struct pp_hwmgr *hwmgr) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + struct fiji_single_dpm_table *mclk_table = &(data->dpm_table.mclk_table); + struct fiji_single_dpm_table *golden_mclk_table = + &(data->golden_dpm_table.mclk_table); + int value; + + value = (mclk_table->dpm_levels[mclk_table->count - 1].value - + golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value) * + 100 / + golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value; + + return value; +} + +static int fiji_set_mclk_od(struct pp_hwmgr *hwmgr, uint32_t value) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + struct fiji_single_dpm_table *golden_mclk_table = + &(data->golden_dpm_table.mclk_table); + struct pp_power_state *ps; + struct fiji_power_state *fiji_ps; + + if (value > 20) + value = 20; + + ps = hwmgr->request_ps; + + if (ps == NULL) + return -EINVAL; + + fiji_ps = cast_phw_fiji_power_state(&ps->hardware); + + fiji_ps->performance_levels[fiji_ps->performance_level_count - 1].memory_clock = + golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value * + value / 100 + + golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value; + + return 0; +} static const struct pp_hwmgr_func fiji_hwmgr_funcs = { .backend_init = &fiji_hwmgr_backend_init, .backend_fini = &fiji_hwmgr_backend_fini, .asic_setup = &fiji_setup_asic_task, .dynamic_state_management_enable = &fiji_enable_dpm_tasks, + .dynamic_state_management_disable = &fiji_disable_dpm_tasks, .force_dpm_level = &fiji_dpm_force_dpm_level, .get_num_of_pp_table_entries = &tonga_get_number_of_powerplay_table_entries, .get_power_state_size = &fiji_get_power_state_size, @@ -5314,24 +5580,18 @@ static const struct pp_hwmgr_func fiji_hwmgr_funcs = { .get_fan_control_mode = fiji_get_fan_control_mode, .check_states_equal = fiji_check_states_equal, .check_smc_update_required_for_display_configuration = fiji_check_smc_update_required_for_display_configuration, - .get_pp_table = fiji_get_pp_table, - .set_pp_table = fiji_set_pp_table, .force_clock_level = fiji_force_clock_level, .print_clock_levels = fiji_print_clock_levels, + .get_sclk_od = fiji_get_sclk_od, + .set_sclk_od = fiji_set_sclk_od, + .get_mclk_od = fiji_get_mclk_od, + .set_mclk_od = fiji_set_mclk_od, }; int fiji_hwmgr_init(struct pp_hwmgr *hwmgr) { - struct fiji_hwmgr *data; - int ret = 0; - - data = kzalloc(sizeof(struct fiji_hwmgr), GFP_KERNEL); - if (data == NULL) - return -ENOMEM; - - hwmgr->backend = data; hwmgr->hwmgr_func = &fiji_hwmgr_funcs; hwmgr->pptable_func = &tonga_pptable_funcs; pp_fiji_thermal_initialize(hwmgr); - return ret; + return 0; } diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.h b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.h index 170edf5a772d..bf67c2a92c68 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.h +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.h @@ -302,9 +302,6 @@ struct fiji_hwmgr { bool pg_acp_init; bool frtc_enabled; bool frtc_status_changed; - - /* soft pptable for re-uploading into smu */ - void *soft_pp_table; }; /* To convert to Q8.8 format for firmware */ diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_powertune.c b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_powertune.c index db23a4068baf..44658451a8d2 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_powertune.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_powertune.c @@ -73,17 +73,18 @@ void fiji_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr) if (!tmp) { phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_PowerContainment); - - phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_CAC); fiji_hwmgr->fast_watermark_threshold = 100; - tmp = 1; - fiji_hwmgr->enable_dte_feature = tmp ? false : true; - fiji_hwmgr->enable_tdc_limit_feature = tmp ? true : false; - fiji_hwmgr->enable_pkg_pwr_tracking_feature = tmp ? true : false; + if (hwmgr->powercontainment_enabled) { + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_PowerContainment); + tmp = 1; + fiji_hwmgr->enable_dte_feature = tmp ? false : true; + fiji_hwmgr->enable_tdc_limit_feature = tmp ? true : false; + fiji_hwmgr->enable_pkg_pwr_tracking_feature = tmp ? true : false; + } } } @@ -459,6 +460,23 @@ int fiji_enable_smc_cac(struct pp_hwmgr *hwmgr) return result; } +int fiji_disable_smc_cac(struct pp_hwmgr *hwmgr) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + int result = 0; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_CAC) && data->cac_enabled) { + int smc_result = smum_send_msg_to_smc(hwmgr->smumgr, + (uint16_t)(PPSMC_MSG_DisableCac)); + PP_ASSERT_WITH_CODE((smc_result == 0), + "Failed to disable CAC in SMC.", result = -1); + + data->cac_enabled = false; + } + return result; +} + int fiji_set_power_limit(struct pp_hwmgr *hwmgr, uint32_t n) { struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); @@ -528,6 +546,48 @@ int fiji_enable_power_containment(struct pp_hwmgr *hwmgr) return result; } +int fiji_disable_power_containment(struct pp_hwmgr *hwmgr) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + int result = 0; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_PowerContainment) && + data->power_containment_features) { + int smc_result; + + if (data->power_containment_features & + POWERCONTAINMENT_FEATURE_TDCLimit) { + smc_result = smum_send_msg_to_smc(hwmgr->smumgr, + (uint16_t)(PPSMC_MSG_TDCLimitDisable)); + PP_ASSERT_WITH_CODE((smc_result == 0), + "Failed to disable TDCLimit in SMC.", + result = smc_result); + } + + if (data->power_containment_features & + POWERCONTAINMENT_FEATURE_DTE) { + smc_result = smum_send_msg_to_smc(hwmgr->smumgr, + (uint16_t)(PPSMC_MSG_DisableDTE)); + PP_ASSERT_WITH_CODE((smc_result == 0), + "Failed to disable DTE in SMC.", + result = smc_result); + } + + if (data->power_containment_features & + POWERCONTAINMENT_FEATURE_PkgPwrLimit) { + smc_result = smum_send_msg_to_smc(hwmgr->smumgr, + (uint16_t)(PPSMC_MSG_PkgPwrLimitDisable)); + PP_ASSERT_WITH_CODE((smc_result == 0), + "Failed to disable PkgPwrTracking in SMC.", + result = smc_result); + } + data->power_containment_features = 0; + } + + return result; +} + int fiji_power_control_set_level(struct pp_hwmgr *hwmgr) { struct phm_ppt_v1_information *table_info = diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_powertune.h b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_powertune.h index 55e58200f33a..fec772421733 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_powertune.h +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_powertune.h @@ -36,6 +36,19 @@ enum fiji_pt_config_reg_type { #define POWERCONTAINMENT_FEATURE_TDCLimit 0x00000002 #define POWERCONTAINMENT_FEATURE_PkgPwrLimit 0x00000004 +#define DIDT_SQ_CTRL0__UNUSED_0_MASK 0xffffffc0 +#define DIDT_SQ_CTRL0__UNUSED_0__SHIFT 0x6 +#define DIDT_TD_CTRL0__UNUSED_0_MASK 0xffffffc0 +#define DIDT_TD_CTRL0__UNUSED_0__SHIFT 0x6 +#define DIDT_TCP_CTRL0__UNUSED_0_MASK 0xffffffc0 +#define DIDT_TCP_CTRL0__UNUSED_0__SHIFT 0x6 +#define DIDT_SQ_TUNING_CTRL__UNUSED_0_MASK 0xe0000000 +#define DIDT_SQ_TUNING_CTRL__UNUSED_0__SHIFT 0x0000001d +#define DIDT_TD_TUNING_CTRL__UNUSED_0_MASK 0xe0000000 +#define DIDT_TD_TUNING_CTRL__UNUSED_0__SHIFT 0x0000001d +#define DIDT_TCP_TUNING_CTRL__UNUSED_0_MASK 0xe0000000 +#define DIDT_TCP_TUNING_CTRL__UNUSED_0__SHIFT 0x0000001d + struct fiji_pt_config_reg { uint32_t offset; uint32_t mask; @@ -58,7 +71,9 @@ void fiji_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr); int fiji_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr); int fiji_populate_pm_fuses(struct pp_hwmgr *hwmgr); int fiji_enable_smc_cac(struct pp_hwmgr *hwmgr); +int fiji_disable_smc_cac(struct pp_hwmgr *hwmgr); int fiji_enable_power_containment(struct pp_hwmgr *hwmgr); +int fiji_disable_power_containment(struct pp_hwmgr *hwmgr); int fiji_set_power_limit(struct pp_hwmgr *hwmgr, uint32_t n); int fiji_power_control_set_level(struct pp_hwmgr *hwmgr); diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c b/drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c index efb77eda7508..789f98ad2615 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c @@ -154,6 +154,30 @@ int phm_enable_dynamic_state_management(struct pp_hwmgr *hwmgr) return ret; } +int phm_disable_dynamic_state_management(struct pp_hwmgr *hwmgr) +{ + int ret = -1; + bool enabled; + + PHM_FUNC_CHECK(hwmgr); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_TablelessHardwareInterface)) { + if (hwmgr->hwmgr_func->dynamic_state_management_disable) + ret = hwmgr->hwmgr_func->dynamic_state_management_disable(hwmgr); + } else { + ret = phm_dispatch_table(hwmgr, + &(hwmgr->disable_dynamic_state_management), + NULL, NULL); + } + + enabled = ret == 0 ? false : true; + + cgs_notify_dpm_enabled(hwmgr->device, enabled); + + return ret; +} + int phm_force_dpm_levels(struct pp_hwmgr *hwmgr, enum amd_dpm_forced_level level) { PHM_FUNC_CHECK(hwmgr); @@ -314,7 +338,7 @@ int phm_store_dal_configuration_data(struct pp_hwmgr *hwmgr, if (hwmgr->hwmgr_func->store_cc6_data == NULL) return -EINVAL; - /* to do pass other display configuration in furture */ + /* TODO: pass other display configuration in the future */ if (hwmgr->hwmgr_func->store_cc6_data) hwmgr->hwmgr_func->store_cc6_data(hwmgr, diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c index 20f20e075588..03b6128ebc20 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c @@ -24,6 +24,7 @@ #include <linux/types.h> #include <linux/kernel.h> #include <linux/slab.h> +#include <drm/amdgpu_drm.h> #include "cgs_common.h" #include "power_state.h" #include "hwmgr.h" @@ -58,12 +59,13 @@ int hwmgr_init(struct amd_pp_init *pp_init, struct pp_instance *handle) hwmgr->hw_revision = pp_init->rev_id; hwmgr->usec_timeout = AMD_MAX_USEC_TIMEOUT; hwmgr->power_source = PP_PowerSource_AC; + hwmgr->powercontainment_enabled = pp_init->powercontainment_enabled; switch (hwmgr->chip_family) { - case AMD_FAMILY_CZ: + case AMDGPU_FAMILY_CZ: cz_hwmgr_init(hwmgr); break; - case AMD_FAMILY_VI: + case AMDGPU_FAMILY_VI: switch (hwmgr->chip_id) { case CHIP_TONGA: tonga_hwmgr_init(hwmgr); @@ -94,6 +96,8 @@ int hwmgr_fini(struct pp_hwmgr *hwmgr) return -EINVAL; /* do hwmgr finish*/ + kfree(hwmgr->hardcode_pp_table); + kfree(hwmgr->backend); kfree(hwmgr->start_thermal_controller.function_list); diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_clockpowergating.c b/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_clockpowergating.c index 8f142a74ad08..aeec25c66aa8 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_clockpowergating.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_clockpowergating.c @@ -106,11 +106,17 @@ int polaris10_phm_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate) data->uvd_power_gated = bgate; if (bgate) { + cgs_set_clockgating_state(hwmgr->device, + AMD_IP_BLOCK_TYPE_UVD, + AMD_CG_STATE_GATE); polaris10_update_uvd_dpm(hwmgr, true); polaris10_phm_powerdown_uvd(hwmgr); } else { polaris10_phm_powerup_uvd(hwmgr); polaris10_update_uvd_dpm(hwmgr, false); + cgs_set_clockgating_state(hwmgr->device, + AMD_IP_BLOCK_TYPE_UVD, + AMD_PG_STATE_UNGATE); } return 0; diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.c index 64ee78f7d41e..9d764c4d253e 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.c @@ -389,6 +389,34 @@ static int polaris10_program_voting_clients(struct pp_hwmgr *hwmgr) return 0; } +static int polaris10_clear_voting_clients(struct pp_hwmgr *hwmgr) +{ + /* Reset voting clients before disabling DPM */ + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + SCLK_PWRMGT_CNTL, RESET_SCLK_CNT, 1); + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + SCLK_PWRMGT_CNTL, RESET_BUSY_CNT, 1); + + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_FREQ_TRAN_VOTING_0, 0); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_FREQ_TRAN_VOTING_1, 0); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_FREQ_TRAN_VOTING_2, 0); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_FREQ_TRAN_VOTING_3, 0); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_FREQ_TRAN_VOTING_4, 0); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_FREQ_TRAN_VOTING_5, 0); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_FREQ_TRAN_VOTING_6, 0); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_FREQ_TRAN_VOTING_7, 0); + + return 0; +} + /** * Get the location of various tables inside the FW image. * @@ -515,6 +543,11 @@ static int polaris10_copy_and_switch_arb_sets(struct pp_hwmgr *hwmgr, return 0; } +static int polaris10_reset_to_default(struct pp_hwmgr *hwmgr) +{ + return smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_ResetToDefaults); +} + /** * Initial switch from ARB F0->F1 * @@ -528,6 +561,21 @@ static int polaris10_initial_switch_from_arbf0_to_f1(struct pp_hwmgr *hwmgr) MC_CG_ARB_FREQ_F0, MC_CG_ARB_FREQ_F1); } +static int polaris10_force_switch_to_arbf0(struct pp_hwmgr *hwmgr) +{ + uint32_t tmp; + + tmp = (cgs_read_ind_register(hwmgr->device, + CGS_IND_REG__SMC, ixSMC_SCRATCH9) & + 0x0000ff00) >> 8; + + if (tmp == MC_CG_ARB_FREQ_F0) + return 0; + + return polaris10_copy_and_switch_arb_sets(hwmgr, + tmp, MC_CG_ARB_FREQ_F0); +} + static int polaris10_setup_default_pcie_table(struct pp_hwmgr *hwmgr) { struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend); @@ -1356,9 +1404,9 @@ static int polaris10_populate_all_memory_levels(struct pp_hwmgr *hwmgr) return result; } - /* in order to prevent MC activity from stutter mode to push DPM up. + /* In order to prevent MC activity from stutter mode to push DPM up, * the UVD change complements this by putting the MCLK in - * a higher state by default such that we are not effected by + * a higher state by default such that we are not affected by * up threshold or and MCLK DPM latency. */ levels[0].ActivityLevel = 0x1f; @@ -1865,9 +1913,8 @@ static int polaris10_populate_vr_config(struct pp_hwmgr *hwmgr, if (POLARIS10_VOLTAGE_CONTROL_BY_SVID2 == data->mvdd_control) { config = VR_SVI2_PLANE_2; table->VRConfig |= (config << VRCONF_MVDD_SHIFT); - } else if (POLARIS10_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) { - config = VR_SMIO_PATTERN_2; - table->VRConfig |= (config << VRCONF_MVDD_SHIFT); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, data->soft_regs_start + + offsetof(SMU74_SoftRegisters, AllowMvddSwitch), 0x1); } else { config = VR_STATIC_VOLTAGE; table->VRConfig |= (config << VRCONF_MVDD_SHIFT); @@ -2237,6 +2284,17 @@ static int polaris10_enable_ulv(struct pp_hwmgr *hwmgr) return 0; } +static int polaris10_disable_ulv(struct pp_hwmgr *hwmgr) +{ + struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend); + struct polaris10_ulv_parm *ulv = &(data->ulv); + + if (ulv->ulv_supported) + return smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_DisableULV); + + return 0; +} + static int polaris10_enable_deep_sleep_master_switch(struct pp_hwmgr *hwmgr) { if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, @@ -2257,6 +2315,21 @@ static int polaris10_enable_deep_sleep_master_switch(struct pp_hwmgr *hwmgr) return 0; } +static int polaris10_disable_deep_sleep_master_switch(struct pp_hwmgr *hwmgr) +{ + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SclkDeepSleep)) { + if (smum_send_msg_to_smc(hwmgr->smumgr, + PPSMC_MSG_MASTER_DeepSleep_OFF)) { + PP_ASSERT_WITH_CODE(false, + "Attempt to disable Master Deep Sleep switch failed!", + return -1); + } + } + + return 0; +} + static int polaris10_enable_sclk_mclk_dpm(struct pp_hwmgr *hwmgr) { struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend); @@ -2354,6 +2427,58 @@ static int polaris10_start_dpm(struct pp_hwmgr *hwmgr) return 0; } +static int polaris10_disable_sclk_mclk_dpm(struct pp_hwmgr *hwmgr) +{ + struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend); + + /* disable SCLK dpm */ + if (!data->sclk_dpm_key_disabled) + PP_ASSERT_WITH_CODE( + (smum_send_msg_to_smc(hwmgr->smumgr, + PPSMC_MSG_DPM_Disable) == 0), + "Failed to disable SCLK DPM!", + return -1); + + /* disable MCLK dpm */ + if (!data->mclk_dpm_key_disabled) { + PP_ASSERT_WITH_CODE( + (smum_send_msg_to_smc(hwmgr->smumgr, + PPSMC_MSG_MCLKDPM_Disable) == 0), + "Failed to disable MCLK DPM!", + return -1); + } + + return 0; +} + +static int polaris10_stop_dpm(struct pp_hwmgr *hwmgr) +{ + struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend); + + /* disable general power management */ + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, GENERAL_PWRMGT, + GLOBAL_PWRMGT_EN, 0); + /* disable sclk deep sleep */ + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SCLK_PWRMGT_CNTL, + DYNAMIC_PM_EN, 0); + + /* disable PCIE dpm */ + if (!data->pcie_dpm_key_disabled) { + PP_ASSERT_WITH_CODE( + (smum_send_msg_to_smc(hwmgr->smumgr, + PPSMC_MSG_PCIeDPM_Disable) == 0), + "Failed to disable pcie DPM during DPM Stop Function!", + return -1); + } + + if (polaris10_disable_sclk_mclk_dpm(hwmgr)) { + printk(KERN_ERR "Failed to disable Sclk DPM and Mclk DPM!"); + return -1; + } + + return 0; +} + static void polaris10_set_dpm_event_sources(struct pp_hwmgr *hwmgr, uint32_t sources) { bool protection; @@ -2411,6 +2536,23 @@ static int polaris10_enable_thermal_auto_throttle(struct pp_hwmgr *hwmgr) return polaris10_enable_auto_throttle_source(hwmgr, PHM_AutoThrottleSource_Thermal); } +static int polaris10_disable_auto_throttle_source(struct pp_hwmgr *hwmgr, + PHM_AutoThrottleSource source) +{ + struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend); + + if (data->active_auto_throttle_sources & (1 << source)) { + data->active_auto_throttle_sources &= ~(1 << source); + polaris10_set_dpm_event_sources(hwmgr, data->active_auto_throttle_sources); + } + return 0; +} + +static int polaris10_disable_thermal_auto_throttle(struct pp_hwmgr *hwmgr) +{ + return polaris10_disable_auto_throttle_source(hwmgr, PHM_AutoThrottleSource_Thermal); +} + int polaris10_pcie_performance_request(struct pp_hwmgr *hwmgr) { struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend); @@ -2532,8 +2674,60 @@ int polaris10_enable_dpm_tasks(struct pp_hwmgr *hwmgr) int polaris10_disable_dpm_tasks(struct pp_hwmgr *hwmgr) { + int tmp_result, result = 0; - return 0; + tmp_result = (polaris10_is_dpm_running(hwmgr)) ? 0 : -1; + PP_ASSERT_WITH_CODE(tmp_result == 0, + "DPM is not running right now, no need to disable DPM!", + return 0); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ThermalController)) + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + GENERAL_PWRMGT, THERMAL_PROTECTION_DIS, 1); + + tmp_result = polaris10_disable_power_containment(hwmgr); + PP_ASSERT_WITH_CODE((tmp_result == 0), + "Failed to disable power containment!", result = tmp_result); + + tmp_result = polaris10_disable_smc_cac(hwmgr); + PP_ASSERT_WITH_CODE((tmp_result == 0), + "Failed to disable SMC CAC!", result = tmp_result); + + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_SPLL_SPREAD_SPECTRUM, SSEN, 0); + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + GENERAL_PWRMGT, DYN_SPREAD_SPECTRUM_EN, 0); + + tmp_result = polaris10_disable_thermal_auto_throttle(hwmgr); + PP_ASSERT_WITH_CODE((tmp_result == 0), + "Failed to disable thermal auto throttle!", result = tmp_result); + + tmp_result = polaris10_stop_dpm(hwmgr); + PP_ASSERT_WITH_CODE((tmp_result == 0), + "Failed to stop DPM!", result = tmp_result); + + tmp_result = polaris10_disable_deep_sleep_master_switch(hwmgr); + PP_ASSERT_WITH_CODE((tmp_result == 0), + "Failed to disable deep sleep master switch!", result = tmp_result); + + tmp_result = polaris10_disable_ulv(hwmgr); + PP_ASSERT_WITH_CODE((tmp_result == 0), + "Failed to disable ULV!", result = tmp_result); + + tmp_result = polaris10_clear_voting_clients(hwmgr); + PP_ASSERT_WITH_CODE((tmp_result == 0), + "Failed to clear voting clients!", result = tmp_result); + + tmp_result = polaris10_reset_to_default(hwmgr); + PP_ASSERT_WITH_CODE((tmp_result == 0), + "Failed to reset to default!", result = tmp_result); + + tmp_result = polaris10_force_switch_to_arbf0(hwmgr); + PP_ASSERT_WITH_CODE((tmp_result == 0), + "Failed to force to switch arbf0!", result = tmp_result); + + return result; } int polaris10_reset_asic_tasks(struct pp_hwmgr *hwmgr) @@ -2544,13 +2738,6 @@ int polaris10_reset_asic_tasks(struct pp_hwmgr *hwmgr) int polaris10_hwmgr_backend_fini(struct pp_hwmgr *hwmgr) { - struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend); - - if (data->soft_pp_table) { - kfree(data->soft_pp_table); - data->soft_pp_table = NULL; - } - return phm_hwmgr_backend_fini(hwmgr); } @@ -2606,8 +2793,13 @@ int polaris10_set_features_platform_caps(struct pp_hwmgr *hwmgr) phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_TCPRamping); - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_PowerContainment); + if (hwmgr->powercontainment_enabled) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_PowerContainment); + else + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_PowerContainment); + phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_CAC); @@ -2679,12 +2871,12 @@ static int polaris10_get_evv_voltages(struct pp_hwmgr *hwmgr) } } - - PP_ASSERT_WITH_CODE(0 == atomctrl_get_voltage_evv_on_sclk_ai(hwmgr, - VOLTAGE_TYPE_VDDC, sclk, vv_id, &vddc), - "Error retrieving EVV voltage value!", - continue); - + if (atomctrl_get_voltage_evv_on_sclk_ai(hwmgr, + VOLTAGE_TYPE_VDDC, + sclk, vv_id, &vddc) != 0) { + printk(KERN_WARNING "failed to retrieving EVV voltage!\n"); + continue; + } /* need to make sure vddc is less than 2v or else, it could burn the ASIC. */ PP_ASSERT_WITH_CODE((vddc < 2000 && vddc != 0), @@ -2915,13 +3107,19 @@ static int polaris10_set_private_data_based_on_pptable(struct pp_hwmgr *hwmgr) int polaris10_hwmgr_backend_init(struct pp_hwmgr *hwmgr) { - struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend); + struct polaris10_hwmgr *data; struct pp_atomctrl_gpio_pin_assignment gpio_pin_assignment; uint32_t temp_reg; int result; struct phm_ppt_v1_information *table_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); + data = kzalloc(sizeof(struct polaris10_hwmgr), GFP_KERNEL); + if (data == NULL) + return -ENOMEM; + + hwmgr->backend = data; + data->dll_default_on = false; data->sram_end = SMC_RAM_END; data->mclk_dpm0_activity_target = 0xa; @@ -3094,7 +3292,7 @@ int polaris10_hwmgr_backend_init(struct pp_hwmgr *hwmgr) sys_info.info_id = CGS_SYSTEM_INFO_PCIE_GEN_INFO; result = cgs_query_system_info(hwmgr->device, &sys_info); if (result) - data->pcie_gen_cap = 0x30007; + data->pcie_gen_cap = AMDGPU_DEFAULT_PCIE_GEN_MASK; else data->pcie_gen_cap = (uint32_t)sys_info.value; if (data->pcie_gen_cap & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3) @@ -3103,7 +3301,7 @@ int polaris10_hwmgr_backend_init(struct pp_hwmgr *hwmgr) sys_info.info_id = CGS_SYSTEM_INFO_PCIE_MLW; result = cgs_query_system_info(hwmgr->device, &sys_info); if (result) - data->pcie_lane_cap = 0x2f0000; + data->pcie_lane_cap = AMDGPU_DEFAULT_PCIE_MLW_MASK; else data->pcie_lane_cap = (uint32_t)sys_info.value; @@ -4753,42 +4951,6 @@ int polaris10_setup_asic_task(struct pp_hwmgr *hwmgr) return result; } -static int polaris10_get_pp_table(struct pp_hwmgr *hwmgr, char **table) -{ - struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend); - - if (!data->soft_pp_table) { - data->soft_pp_table = kmemdup(hwmgr->soft_pp_table, - hwmgr->soft_pp_table_size, - GFP_KERNEL); - if (!data->soft_pp_table) - return -ENOMEM; - } - - *table = (char *)&data->soft_pp_table; - - return hwmgr->soft_pp_table_size; -} - -static int polaris10_set_pp_table(struct pp_hwmgr *hwmgr, const char *buf, size_t size) -{ - struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend); - - if (!data->soft_pp_table) { - data->soft_pp_table = kzalloc(hwmgr->soft_pp_table_size, GFP_KERNEL); - if (!data->soft_pp_table) - return -ENOMEM; - } - - memcpy(data->soft_pp_table, buf, size); - - hwmgr->soft_pp_table = data->soft_pp_table; - - /* TODO: re-init powerplay to implement modified pptable */ - - return 0; -} - static int polaris10_force_clock_level(struct pp_hwmgr *hwmgr, enum pp_clock_type type, uint32_t mask) { @@ -4931,6 +5093,89 @@ static int polaris10_get_fan_control_mode(struct pp_hwmgr *hwmgr) CG_FDO_CTRL2, FDO_PWM_MODE); } +static int polaris10_get_sclk_od(struct pp_hwmgr *hwmgr) +{ + struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend); + struct polaris10_single_dpm_table *sclk_table = &(data->dpm_table.sclk_table); + struct polaris10_single_dpm_table *golden_sclk_table = + &(data->golden_dpm_table.sclk_table); + int value; + + value = (sclk_table->dpm_levels[sclk_table->count - 1].value - + golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value) * + 100 / + golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value; + + return value; +} + +static int polaris10_set_sclk_od(struct pp_hwmgr *hwmgr, uint32_t value) +{ + struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend); + struct polaris10_single_dpm_table *golden_sclk_table = + &(data->golden_dpm_table.sclk_table); + struct pp_power_state *ps; + struct polaris10_power_state *polaris10_ps; + + if (value > 20) + value = 20; + + ps = hwmgr->request_ps; + + if (ps == NULL) + return -EINVAL; + + polaris10_ps = cast_phw_polaris10_power_state(&ps->hardware); + + polaris10_ps->performance_levels[polaris10_ps->performance_level_count - 1].engine_clock = + golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value * + value / 100 + + golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value; + + return 0; +} + +static int polaris10_get_mclk_od(struct pp_hwmgr *hwmgr) +{ + struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend); + struct polaris10_single_dpm_table *mclk_table = &(data->dpm_table.mclk_table); + struct polaris10_single_dpm_table *golden_mclk_table = + &(data->golden_dpm_table.mclk_table); + int value; + + value = (mclk_table->dpm_levels[mclk_table->count - 1].value - + golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value) * + 100 / + golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value; + + return value; +} + +static int polaris10_set_mclk_od(struct pp_hwmgr *hwmgr, uint32_t value) +{ + struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend); + struct polaris10_single_dpm_table *golden_mclk_table = + &(data->golden_dpm_table.mclk_table); + struct pp_power_state *ps; + struct polaris10_power_state *polaris10_ps; + + if (value > 20) + value = 20; + + ps = hwmgr->request_ps; + + if (ps == NULL) + return -EINVAL; + + polaris10_ps = cast_phw_polaris10_power_state(&ps->hardware); + + polaris10_ps->performance_levels[polaris10_ps->performance_level_count - 1].memory_clock = + golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value * + value / 100 + + golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value; + + return 0; +} static const struct pp_hwmgr_func polaris10_hwmgr_funcs = { .backend_init = &polaris10_hwmgr_backend_init, .backend_fini = &polaris10_hwmgr_backend_fini, @@ -4969,22 +5214,17 @@ static const struct pp_hwmgr_func polaris10_hwmgr_funcs = { .check_states_equal = polaris10_check_states_equal, .set_fan_control_mode = polaris10_set_fan_control_mode, .get_fan_control_mode = polaris10_get_fan_control_mode, - .get_pp_table = polaris10_get_pp_table, - .set_pp_table = polaris10_set_pp_table, .force_clock_level = polaris10_force_clock_level, .print_clock_levels = polaris10_print_clock_levels, .enable_per_cu_power_gating = polaris10_phm_enable_per_cu_power_gating, + .get_sclk_od = polaris10_get_sclk_od, + .set_sclk_od = polaris10_set_sclk_od, + .get_mclk_od = polaris10_get_mclk_od, + .set_mclk_od = polaris10_set_mclk_od, }; int polaris10_hwmgr_init(struct pp_hwmgr *hwmgr) { - struct polaris10_hwmgr *data; - - data = kzalloc (sizeof(struct polaris10_hwmgr), GFP_KERNEL); - if (data == NULL) - return -ENOMEM; - - hwmgr->backend = data; hwmgr->hwmgr_func = &polaris10_hwmgr_funcs; hwmgr->pptable_func = &tonga_pptable_funcs; pp_polaris10_thermal_initialize(hwmgr); diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.h b/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.h index d717789441f5..fd38b0d7a3c2 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.h +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.h @@ -309,10 +309,6 @@ struct polaris10_hwmgr { uint32_t up_hyst; uint32_t disable_dpm_mask; bool apply_optimized_settings; - - /* soft pptable for re-uploading into smu */ - void *soft_pp_table; - uint32_t avfs_vdroop_override_setting; bool apply_avfs_cks_off_voltage; }; diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_powertune.c b/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_powertune.c index ae96f14b827c..5620e268b553 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_powertune.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_powertune.c @@ -312,6 +312,23 @@ int polaris10_enable_smc_cac(struct pp_hwmgr *hwmgr) return result; } +int polaris10_disable_smc_cac(struct pp_hwmgr *hwmgr) +{ + struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend); + int result = 0; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_CAC) && data->cac_enabled) { + int smc_result = smum_send_msg_to_smc(hwmgr->smumgr, + (uint16_t)(PPSMC_MSG_DisableCac)); + PP_ASSERT_WITH_CODE((smc_result == 0), + "Failed to disable CAC in SMC.", result = -1); + + data->cac_enabled = false; + } + return result; +} + int polaris10_set_power_limit(struct pp_hwmgr *hwmgr, uint32_t n) { struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend); @@ -373,6 +390,48 @@ int polaris10_enable_power_containment(struct pp_hwmgr *hwmgr) return result; } +int polaris10_disable_power_containment(struct pp_hwmgr *hwmgr) +{ + struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend); + int result = 0; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_PowerContainment) && + data->power_containment_features) { + int smc_result; + + if (data->power_containment_features & + POWERCONTAINMENT_FEATURE_TDCLimit) { + smc_result = smum_send_msg_to_smc(hwmgr->smumgr, + (uint16_t)(PPSMC_MSG_TDCLimitDisable)); + PP_ASSERT_WITH_CODE((smc_result == 0), + "Failed to disable TDCLimit in SMC.", + result = smc_result); + } + + if (data->power_containment_features & + POWERCONTAINMENT_FEATURE_DTE) { + smc_result = smum_send_msg_to_smc(hwmgr->smumgr, + (uint16_t)(PPSMC_MSG_DisableDTE)); + PP_ASSERT_WITH_CODE((smc_result == 0), + "Failed to disable DTE in SMC.", + result = smc_result); + } + + if (data->power_containment_features & + POWERCONTAINMENT_FEATURE_PkgPwrLimit) { + smc_result = smum_send_msg_to_smc(hwmgr->smumgr, + (uint16_t)(PPSMC_MSG_PkgPwrLimitDisable)); + PP_ASSERT_WITH_CODE((smc_result == 0), + "Failed to disable PkgPwrTracking in SMC.", + result = smc_result); + } + data->power_containment_features = 0; + } + + return result; +} + int polaris10_power_control_set_level(struct pp_hwmgr *hwmgr) { struct phm_ppt_v1_information *table_info = diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_powertune.h b/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_powertune.h index 68bc1cb6d40c..d492d6d28867 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_powertune.h +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_powertune.h @@ -31,6 +31,19 @@ enum polaris10_pt_config_reg_type { POLARIS10_CONFIGREG_MAX }; +#define DIDT_SQ_CTRL0__UNUSED_0_MASK 0xfffc0000 +#define DIDT_SQ_CTRL0__UNUSED_0__SHIFT 0x12 +#define DIDT_TD_CTRL0__UNUSED_0_MASK 0xfffc0000 +#define DIDT_TD_CTRL0__UNUSED_0__SHIFT 0x12 +#define DIDT_TCP_CTRL0__UNUSED_0_MASK 0xfffc0000 +#define DIDT_TCP_CTRL0__UNUSED_0__SHIFT 0x12 +#define DIDT_SQ_TUNING_CTRL__UNUSED_0_MASK 0xc0000000 +#define DIDT_SQ_TUNING_CTRL__UNUSED_0__SHIFT 0x0000001e +#define DIDT_TD_TUNING_CTRL__UNUSED_0_MASK 0xc0000000 +#define DIDT_TD_TUNING_CTRL__UNUSED_0__SHIFT 0x0000001e +#define DIDT_TCP_TUNING_CTRL__UNUSED_0_MASK 0xc0000000 +#define DIDT_TCP_TUNING_CTRL__UNUSED_0__SHIFT 0x0000001e + /* PowerContainment Features */ #define POWERCONTAINMENT_FEATURE_DTE 0x00000001 #define POWERCONTAINMENT_FEATURE_TDCLimit 0x00000002 @@ -62,7 +75,9 @@ void polaris10_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr); int polaris10_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr); int polaris10_populate_pm_fuses(struct pp_hwmgr *hwmgr); int polaris10_enable_smc_cac(struct pp_hwmgr *hwmgr); +int polaris10_disable_smc_cac(struct pp_hwmgr *hwmgr); int polaris10_enable_power_containment(struct pp_hwmgr *hwmgr); +int polaris10_disable_power_containment(struct pp_hwmgr *hwmgr); int polaris10_set_power_limit(struct pp_hwmgr *hwmgr, uint32_t n); int polaris10_power_control_set_level(struct pp_hwmgr *hwmgr); diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.c b/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.c index bf4e18fd3872..5d70e2c47faf 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.c @@ -552,13 +552,13 @@ static bool atomctrl_lookup_gpio_pin( pin_assignment->ucGpioPinBitShift; gpio_pin_assignment->us_gpio_pin_aindex = le16_to_cpu(pin_assignment->usGpioPin_AIndex); - return false; + return true; } offset += offsetof(ATOM_GPIO_PIN_ASSIGNMENT, ucGPIO_ID) + 1; } - return true; + return false; } /** diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c b/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c index 2f1a14fe05b1..35bc8a29b773 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c @@ -794,15 +794,18 @@ static const ATOM_PPLIB_STATE_V2 *get_state_entry_v2( static const ATOM_PPLIB_POWERPLAYTABLE *get_powerplay_table( struct pp_hwmgr *hwmgr) { - const void *table_addr = NULL; + const void *table_addr = hwmgr->soft_pp_table; uint8_t frev, crev; uint16_t size; - table_addr = cgs_atom_get_data_table(hwmgr->device, - GetIndexIntoMasterTable(DATA, PowerPlayInfo), - &size, &frev, &crev); + if (!table_addr) { + table_addr = cgs_atom_get_data_table(hwmgr->device, + GetIndexIntoMasterTable(DATA, PowerPlayInfo), + &size, &frev, &crev); - hwmgr->soft_pp_table = table_addr; + hwmgr->soft_pp_table = table_addr; + hwmgr->soft_pp_table_size = size; + } return (const ATOM_PPLIB_POWERPLAYTABLE *)table_addr; } @@ -1499,7 +1502,7 @@ int get_number_of_vce_state_table_entries( const ATOM_PPLIB_VCE_State_Table *vce_table = get_vce_state_table(hwmgr, table); - if (vce_table > 0) + if (vce_table) return vce_table->numEntries; return 0; @@ -1589,11 +1592,6 @@ static int pp_tables_initialize(struct pp_hwmgr *hwmgr) static int pp_tables_uninitialize(struct pp_hwmgr *hwmgr) { - if (NULL != hwmgr->soft_pp_table) { - kfree(hwmgr->soft_pp_table); - hwmgr->soft_pp_table = NULL; - } - if (NULL != hwmgr->dyn_state.vddc_dependency_on_sclk) { kfree(hwmgr->dyn_state.vddc_dependency_on_sclk); hwmgr->dyn_state.vddc_dependency_on_sclk = NULL; diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c index 233eb7f36c1d..6c4553cf8023 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c @@ -3026,8 +3026,8 @@ int tonga_init_smc_table(struct pp_hwmgr *hwmgr) reg_value = 0; if ((0 == reg_value) && - (0 == atomctrl_get_pp_assign_pin(hwmgr, - VDDC_VRHOT_GPIO_PINID, &gpio_pin_assignment))) { + (atomctrl_get_pp_assign_pin(hwmgr, VDDC_VRHOT_GPIO_PINID, + &gpio_pin_assignment))) { table->VRHotGpio = gpio_pin_assignment.uc_gpio_pin_bit_shift; phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_RegulatorHot); @@ -3040,8 +3040,8 @@ int tonga_init_smc_table(struct pp_hwmgr *hwmgr) /* ACDC Switch GPIO */ reg_value = 0; if ((0 == reg_value) && - (0 == atomctrl_get_pp_assign_pin(hwmgr, - PP_AC_DC_SWITCH_GPIO_PINID, &gpio_pin_assignment))) { + (atomctrl_get_pp_assign_pin(hwmgr, PP_AC_DC_SWITCH_GPIO_PINID, + &gpio_pin_assignment))) { table->AcDcGpio = gpio_pin_assignment.uc_gpio_pin_bit_shift; phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_AutomaticDCTransition); @@ -3063,8 +3063,7 @@ int tonga_init_smc_table(struct pp_hwmgr *hwmgr) } reg_value = 0; - if ((0 == reg_value) && - (0 == atomctrl_get_pp_assign_pin(hwmgr, + if ((0 == reg_value) && (atomctrl_get_pp_assign_pin(hwmgr, THERMAL_INT_OUTPUT_GPIO_PINID, &gpio_pin_assignment))) { phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_ThermalOutGPIO); @@ -4422,13 +4421,6 @@ int tonga_reset_asic_tasks(struct pp_hwmgr *hwmgr) int tonga_hwmgr_backend_fini(struct pp_hwmgr *hwmgr) { - struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend); - - if (data->soft_pp_table) { - kfree(data->soft_pp_table); - data->soft_pp_table = NULL; - } - return phm_hwmgr_backend_fini(hwmgr); } @@ -4442,7 +4434,7 @@ int tonga_hwmgr_backend_init(struct pp_hwmgr *hwmgr) { int result = 0; SMU72_Discrete_DpmTable *table = NULL; - tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend); + tonga_hwmgr *data; pp_atomctrl_gpio_pin_assignment gpio_pin_assignment; struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); phw_tonga_ulv_parm *ulv; @@ -4451,6 +4443,12 @@ int tonga_hwmgr_backend_init(struct pp_hwmgr *hwmgr) PP_ASSERT_WITH_CODE((NULL != hwmgr), "Invalid Parameter!", return -1;); + data = kzalloc(sizeof(struct tonga_hwmgr), GFP_KERNEL); + if (data == NULL) + return -ENOMEM; + + hwmgr->backend = data; + data->dll_defaule_on = 0; data->sram_end = SMC_RAM_END; @@ -4571,7 +4569,7 @@ int tonga_hwmgr_backend_init(struct pp_hwmgr *hwmgr) * if ucGPIO_ID=VDDC_PCC_GPIO_PINID in GPIO_LUTable, * Peak Current Control feature is enabled and we should program PCC HW register */ - if (0 == atomctrl_get_pp_assign_pin(hwmgr, VDDC_PCC_GPIO_PINID, &gpio_pin_assignment)) { + if (atomctrl_get_pp_assign_pin(hwmgr, VDDC_PCC_GPIO_PINID, &gpio_pin_assignment)) { uint32_t temp_reg = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCNB_PWRMGT_CNTL); @@ -4639,7 +4637,7 @@ int tonga_hwmgr_backend_init(struct pp_hwmgr *hwmgr) sys_info.info_id = CGS_SYSTEM_INFO_PCIE_GEN_INFO; result = cgs_query_system_info(hwmgr->device, &sys_info); if (result) - data->pcie_gen_cap = 0x30007; + data->pcie_gen_cap = AMDGPU_DEFAULT_PCIE_GEN_MASK; else data->pcie_gen_cap = (uint32_t)sys_info.value; if (data->pcie_gen_cap & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3) @@ -4648,7 +4646,7 @@ int tonga_hwmgr_backend_init(struct pp_hwmgr *hwmgr) sys_info.info_id = CGS_SYSTEM_INFO_PCIE_MLW; result = cgs_query_system_info(hwmgr->device, &sys_info); if (result) - data->pcie_lane_cap = 0x2f0000; + data->pcie_lane_cap = AMDGPU_DEFAULT_PCIE_MLW_MASK; else data->pcie_lane_cap = (uint32_t)sys_info.value; } else { @@ -6031,42 +6029,6 @@ static int tonga_get_fan_control_mode(struct pp_hwmgr *hwmgr) CG_FDO_CTRL2, FDO_PWM_MODE); } -static int tonga_get_pp_table(struct pp_hwmgr *hwmgr, char **table) -{ - struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend); - - if (!data->soft_pp_table) { - data->soft_pp_table = kmemdup(hwmgr->soft_pp_table, - hwmgr->soft_pp_table_size, - GFP_KERNEL); - if (!data->soft_pp_table) - return -ENOMEM; - } - - *table = (char *)&data->soft_pp_table; - - return hwmgr->soft_pp_table_size; -} - -static int tonga_set_pp_table(struct pp_hwmgr *hwmgr, const char *buf, size_t size) -{ - struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend); - - if (!data->soft_pp_table) { - data->soft_pp_table = kzalloc(hwmgr->soft_pp_table_size, GFP_KERNEL); - if (!data->soft_pp_table) - return -ENOMEM; - } - - memcpy(data->soft_pp_table, buf, size); - - hwmgr->soft_pp_table = data->soft_pp_table; - - /* TODO: re-init powerplay to implement modified pptable */ - - return 0; -} - static int tonga_force_clock_level(struct pp_hwmgr *hwmgr, enum pp_clock_type type, uint32_t mask) { @@ -6174,11 +6136,96 @@ static int tonga_print_clock_levels(struct pp_hwmgr *hwmgr, return size; } +static int tonga_get_sclk_od(struct pp_hwmgr *hwmgr) +{ + struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend); + struct tonga_single_dpm_table *sclk_table = &(data->dpm_table.sclk_table); + struct tonga_single_dpm_table *golden_sclk_table = + &(data->golden_dpm_table.sclk_table); + int value; + + value = (sclk_table->dpm_levels[sclk_table->count - 1].value - + golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value) * + 100 / + golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value; + + return value; +} + +static int tonga_set_sclk_od(struct pp_hwmgr *hwmgr, uint32_t value) +{ + struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend); + struct tonga_single_dpm_table *golden_sclk_table = + &(data->golden_dpm_table.sclk_table); + struct pp_power_state *ps; + struct tonga_power_state *tonga_ps; + + if (value > 20) + value = 20; + + ps = hwmgr->request_ps; + + if (ps == NULL) + return -EINVAL; + + tonga_ps = cast_phw_tonga_power_state(&ps->hardware); + + tonga_ps->performance_levels[tonga_ps->performance_level_count - 1].engine_clock = + golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value * + value / 100 + + golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value; + + return 0; +} + +static int tonga_get_mclk_od(struct pp_hwmgr *hwmgr) +{ + struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend); + struct tonga_single_dpm_table *mclk_table = &(data->dpm_table.mclk_table); + struct tonga_single_dpm_table *golden_mclk_table = + &(data->golden_dpm_table.mclk_table); + int value; + + value = (mclk_table->dpm_levels[mclk_table->count - 1].value - + golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value) * + 100 / + golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value; + + return value; +} + +static int tonga_set_mclk_od(struct pp_hwmgr *hwmgr, uint32_t value) +{ + struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend); + struct tonga_single_dpm_table *golden_mclk_table = + &(data->golden_dpm_table.mclk_table); + struct pp_power_state *ps; + struct tonga_power_state *tonga_ps; + + if (value > 20) + value = 20; + + ps = hwmgr->request_ps; + + if (ps == NULL) + return -EINVAL; + + tonga_ps = cast_phw_tonga_power_state(&ps->hardware); + + tonga_ps->performance_levels[tonga_ps->performance_level_count - 1].memory_clock = + golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value * + value / 100 + + golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value; + + return 0; +} + static const struct pp_hwmgr_func tonga_hwmgr_funcs = { .backend_init = &tonga_hwmgr_backend_init, .backend_fini = &tonga_hwmgr_backend_fini, .asic_setup = &tonga_setup_asic_task, .dynamic_state_management_enable = &tonga_enable_dpm_tasks, + .dynamic_state_management_disable = &tonga_disable_dpm_tasks, .apply_state_adjust_rules = tonga_apply_state_adjust_rules, .force_dpm_level = &tonga_force_dpm_level, .power_state_set = tonga_set_power_state_tasks, @@ -6212,22 +6259,16 @@ static const struct pp_hwmgr_func tonga_hwmgr_funcs = { .check_states_equal = tonga_check_states_equal, .set_fan_control_mode = tonga_set_fan_control_mode, .get_fan_control_mode = tonga_get_fan_control_mode, - .get_pp_table = tonga_get_pp_table, - .set_pp_table = tonga_set_pp_table, .force_clock_level = tonga_force_clock_level, .print_clock_levels = tonga_print_clock_levels, + .get_sclk_od = tonga_get_sclk_od, + .set_sclk_od = tonga_set_sclk_od, + .get_mclk_od = tonga_get_mclk_od, + .set_mclk_od = tonga_set_mclk_od, }; int tonga_hwmgr_init(struct pp_hwmgr *hwmgr) { - tonga_hwmgr *data; - - data = kzalloc (sizeof(tonga_hwmgr), GFP_KERNEL); - if (data == NULL) - return -ENOMEM; - memset(data, 0x00, sizeof(tonga_hwmgr)); - - hwmgr->backend = data; hwmgr->hwmgr_func = &tonga_hwmgr_funcs; hwmgr->pptable_func = &tonga_pptable_funcs; pp_tonga_thermal_initialize(hwmgr); diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.h b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.h index 573cd39fe78d..3961884bfa9b 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.h +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.h @@ -352,9 +352,6 @@ struct tonga_hwmgr { bool samu_power_gated; /* 1: gated, 0:not gated */ bool acp_power_gated; /* 1: gated, 0:not gated */ bool pg_acp_init; - - /* soft pptable for re-uploading into smu */ - void *soft_pp_table; }; typedef struct tonga_hwmgr tonga_hwmgr; diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_processpptables.c b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_processpptables.c index 671fdb4d615a..94d6b472e1fe 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_processpptables.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_processpptables.c @@ -1077,9 +1077,6 @@ int tonga_pp_tables_uninitialize(struct pp_hwmgr *hwmgr) struct phm_ppt_v1_information *pp_table_information = (struct phm_ppt_v1_information *)(hwmgr->pptable); - if (NULL != hwmgr->soft_pp_table) - hwmgr->soft_pp_table = NULL; - kfree(pp_table_information->vdd_dep_on_sclk); pp_table_information->vdd_dep_on_sclk = NULL; diff --git a/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h b/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h index 50b367d44307..b764c8c05ec8 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h +++ b/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h @@ -132,6 +132,7 @@ struct amd_pp_init { uint32_t chip_family; uint32_t chip_id; uint32_t rev_id; + bool powercontainment_enabled; }; enum amd_pp_display_config_type{ AMD_PP_DisplayConfigType_None = 0, @@ -342,6 +343,10 @@ struct amd_powerplay_funcs { int (*set_pp_table)(void *handle, const char *buf, size_t size); int (*force_clock_level)(void *handle, enum pp_clock_type type, uint32_t mask); int (*print_clock_levels)(void *handle, enum pp_clock_type type, char *buf); + int (*get_sclk_od)(void *handle); + int (*set_sclk_od)(void *handle, uint32_t value); + int (*get_mclk_od)(void *handle); + int (*set_mclk_od)(void *handle, uint32_t value); }; struct amd_powerplay { @@ -355,6 +360,8 @@ int amd_powerplay_init(struct amd_pp_init *pp_init, int amd_powerplay_fini(void *handle); +int amd_powerplay_reset(void *handle); + int amd_powerplay_display_configuration_change(void *handle, const struct amd_pp_display_configuration *input); diff --git a/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h b/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h index 56f712c7d07a..962cb5385951 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h +++ b/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h @@ -340,6 +340,7 @@ extern int phm_powergate_vce(struct pp_hwmgr *hwmgr, bool gate); extern int phm_powerdown_uvd(struct pp_hwmgr *hwmgr); extern int phm_setup_asic(struct pp_hwmgr *hwmgr); extern int phm_enable_dynamic_state_management(struct pp_hwmgr *hwmgr); +extern int phm_disable_dynamic_state_management(struct pp_hwmgr *hwmgr); extern void phm_init_dynamic_caps(struct pp_hwmgr *hwmgr); extern bool phm_is_hw_access_blocked(struct pp_hwmgr *hwmgr); extern int phm_block_hw_access(struct pp_hwmgr *hwmgr, bool block); diff --git a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h index 28f571449495..0bbc42a224e5 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h +++ b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h @@ -278,6 +278,8 @@ struct pp_hwmgr_func { int (*dynamic_state_management_enable)( struct pp_hwmgr *hw_mgr); + int (*dynamic_state_management_disable)( + struct pp_hwmgr *hw_mgr); int (*patch_boot_state)(struct pp_hwmgr *hwmgr, struct pp_hw_power_state *hw_ps); @@ -333,11 +335,13 @@ struct pp_hwmgr_func { int (*get_clock_by_type)(struct pp_hwmgr *hwmgr, enum amd_pp_clock_type type, struct amd_pp_clocks *clocks); int (*get_max_high_clocks)(struct pp_hwmgr *hwmgr, struct amd_pp_simple_clock_info *clocks); int (*power_off_asic)(struct pp_hwmgr *hwmgr); - int (*get_pp_table)(struct pp_hwmgr *hwmgr, char **table); - int (*set_pp_table)(struct pp_hwmgr *hwmgr, const char *buf, size_t size); int (*force_clock_level)(struct pp_hwmgr *hwmgr, enum pp_clock_type type, uint32_t mask); int (*print_clock_levels)(struct pp_hwmgr *hwmgr, enum pp_clock_type type, char *buf); int (*enable_per_cu_power_gating)(struct pp_hwmgr *hwmgr, bool enable); + int (*get_sclk_od)(struct pp_hwmgr *hwmgr); + int (*set_sclk_od)(struct pp_hwmgr *hwmgr, uint32_t value); + int (*get_mclk_od)(struct pp_hwmgr *hwmgr); + int (*set_mclk_od)(struct pp_hwmgr *hwmgr, uint32_t value); }; struct pp_table_func { @@ -578,6 +582,7 @@ struct pp_hwmgr { struct pp_smumgr *smumgr; const void *soft_pp_table; uint32_t soft_pp_table_size; + void *hardcode_pp_table; bool need_pp_table_upload; enum amd_dpm_forced_level dpm_level; bool block_hw_access; @@ -607,6 +612,7 @@ struct pp_hwmgr { uint32_t num_ps; struct pp_thermal_controller_info thermal_controller; bool fan_ctrl_is_in_default_mode; + bool powercontainment_enabled; uint32_t fan_ctrl_default_mode; uint32_t tmin; struct phm_microcode_version_info microcode_version_info; diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c index 0728c1e3d97a..7723473e51a0 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c @@ -23,6 +23,7 @@ #include <linux/types.h> #include <linux/kernel.h> #include <linux/slab.h> +#include <drm/amdgpu_drm.h> #include "pp_instance.h" #include "smumgr.h" #include "cgs_common.h" @@ -52,10 +53,10 @@ int smum_init(struct amd_pp_init *pp_init, struct pp_instance *handle) handle->smu_mgr = smumgr; switch (smumgr->chip_family) { - case AMD_FAMILY_CZ: + case AMDGPU_FAMILY_CZ: cz_smum_init(smumgr); break; - case AMD_FAMILY_VI: + case AMDGPU_FAMILY_VI: switch (smumgr->chip_id) { case CHIP_TONGA: tonga_smum_init(smumgr); |