diff options
Diffstat (limited to 'drivers/gpu/drm/amd/pm/swsmu')
-rw-r--r-- | drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 28 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c | 101 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 302 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 120 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c | 69 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c | 310 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c | 216 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/pm/swsmu/smu12/smu_v12_0.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/pm/swsmu/smu_internal.h | 1 |
10 files changed, 485 insertions, 667 deletions
diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 39990790ed67..cf999b7a2164 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -405,6 +405,8 @@ static int smu_set_funcs(struct amdgpu_device *adev) break; case CHIP_VANGOGH: vangogh_set_ppt_funcs(smu); + /* enable the OD by default to allow the fine grain tuning function */ + smu->od_enabled = true; break; default: return -EINVAL; @@ -474,6 +476,8 @@ static int smu_late_init(void *handle) struct smu_context *smu = &adev->smu; int ret = 0; + smu_set_fine_grain_gfx_freq_parameters(smu); + if (adev->asic_type == CHIP_VANGOGH) return 0; @@ -843,7 +847,7 @@ static int smu_sw_init(void *handle) smu->smu_dpm.dpm_level = AMD_DPM_FORCED_LEVEL_AUTO; smu->smu_dpm.requested_dpm_level = AMD_DPM_FORCED_LEVEL_AUTO; - if (!amdgpu_sriov_vf(adev)) { + if (!amdgpu_sriov_vf(adev) || (adev->asic_type != CHIP_NAVI12)) { ret = smu_init_microcode(smu); if (ret) { dev_err(adev->dev, "Failed to load smu firmware!\n"); @@ -914,11 +918,15 @@ static int smu_smc_hw_setup(struct smu_context *smu) { struct amdgpu_device *adev = smu->adev; uint32_t pcie_gen = 0, pcie_width = 0; - int ret; + int ret = 0; if (adev->in_suspend && smu_is_dpm_running(smu)) { dev_info(adev->dev, "dpm has been enabled\n"); - return 0; + /* this is needed specifically */ + if ((adev->asic_type >= CHIP_SIENNA_CICHLID) && + (adev->asic_type <= CHIP_DIMGREY_CAVEFISH)) + ret = smu_system_features_control(smu, true); + return ret; } ret = smu_init_display_count(smu, 0); @@ -1179,7 +1187,7 @@ static int smu_disable_dpms(struct smu_context *smu) */ if (smu->uploading_custom_pp_table && (adev->asic_type >= CHIP_NAVI10) && - (adev->asic_type <= CHIP_NAVY_FLOUNDER)) + (adev->asic_type <= CHIP_DIMGREY_CAVEFISH)) return 0; /* @@ -2529,3 +2537,15 @@ int smu_enable_mgpu_fan_boost(struct smu_context *smu) return ret; } + +int smu_gfx_state_change_set(struct smu_context *smu, uint32_t state) +{ + int ret = 0; + + mutex_lock(&smu->mutex); + if (smu->ppt_funcs->gfx_state_change_set) + ret = smu->ppt_funcs->gfx_state_change_set(smu, state); + mutex_unlock(&smu->mutex); + + return ret; +} diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c index 4fd850e58004..cd7b411457ff 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c @@ -1000,77 +1000,6 @@ static int arcturus_get_thermal_temperature_range(struct smu_context *smu, return 0; } -static int arcturus_get_current_activity_percent(struct smu_context *smu, - enum amd_pp_sensors sensor, - uint32_t *value) -{ - int ret = 0; - - if (!value) - return -EINVAL; - - switch (sensor) { - case AMDGPU_PP_SENSOR_GPU_LOAD: - ret = arcturus_get_smu_metrics_data(smu, - METRICS_AVERAGE_GFXACTIVITY, - value); - break; - case AMDGPU_PP_SENSOR_MEM_LOAD: - ret = arcturus_get_smu_metrics_data(smu, - METRICS_AVERAGE_MEMACTIVITY, - value); - break; - default: - dev_err(smu->adev->dev, "Invalid sensor for retrieving clock activity\n"); - return -EINVAL; - } - - return ret; -} - -static int arcturus_get_gpu_power(struct smu_context *smu, uint32_t *value) -{ - if (!value) - return -EINVAL; - - return arcturus_get_smu_metrics_data(smu, - METRICS_AVERAGE_SOCKETPOWER, - value); -} - -static int arcturus_thermal_get_temperature(struct smu_context *smu, - enum amd_pp_sensors sensor, - uint32_t *value) -{ - int ret = 0; - - if (!value) - return -EINVAL; - - switch (sensor) { - case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: - ret = arcturus_get_smu_metrics_data(smu, - METRICS_TEMPERATURE_HOTSPOT, - value); - break; - case AMDGPU_PP_SENSOR_EDGE_TEMP: - ret = arcturus_get_smu_metrics_data(smu, - METRICS_TEMPERATURE_EDGE, - value); - break; - case AMDGPU_PP_SENSOR_MEM_TEMP: - ret = arcturus_get_smu_metrics_data(smu, - METRICS_TEMPERATURE_MEM, - value); - break; - default: - dev_err(smu->adev->dev, "Invalid sensor for retrieving temp\n"); - return -EINVAL; - } - - return ret; -} - static int arcturus_read_sensor(struct smu_context *smu, enum amd_pp_sensors sensor, void *data, uint32_t *size) @@ -1092,21 +1021,39 @@ static int arcturus_read_sensor(struct smu_context *smu, *size = 4; break; case AMDGPU_PP_SENSOR_MEM_LOAD: + ret = arcturus_get_smu_metrics_data(smu, + METRICS_AVERAGE_MEMACTIVITY, + (uint32_t *)data); + *size = 4; + break; case AMDGPU_PP_SENSOR_GPU_LOAD: - ret = arcturus_get_current_activity_percent(smu, - sensor, - (uint32_t *)data); + ret = arcturus_get_smu_metrics_data(smu, + METRICS_AVERAGE_GFXACTIVITY, + (uint32_t *)data); *size = 4; break; case AMDGPU_PP_SENSOR_GPU_POWER: - ret = arcturus_get_gpu_power(smu, (uint32_t *)data); + ret = arcturus_get_smu_metrics_data(smu, + METRICS_AVERAGE_SOCKETPOWER, + (uint32_t *)data); *size = 4; break; case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: + ret = arcturus_get_smu_metrics_data(smu, + METRICS_TEMPERATURE_HOTSPOT, + (uint32_t *)data); + *size = 4; + break; case AMDGPU_PP_SENSOR_EDGE_TEMP: + ret = arcturus_get_smu_metrics_data(smu, + METRICS_TEMPERATURE_EDGE, + (uint32_t *)data); + *size = 4; + break; case AMDGPU_PP_SENSOR_MEM_TEMP: - ret = arcturus_thermal_get_temperature(smu, sensor, - (uint32_t *)data); + ret = arcturus_get_smu_metrics_data(smu, + METRICS_TEMPERATURE_MEM, + (uint32_t *)data); *size = 4; break; case AMDGPU_PP_SENSOR_GFX_MCLK: diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c index ef1a62e86a0e..51e83123f72a 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c @@ -1302,44 +1302,6 @@ static int navi10_display_config_changed(struct smu_context *smu) return ret; } -static int navi10_get_gpu_power(struct smu_context *smu, uint32_t *value) -{ - if (!value) - return -EINVAL; - - return navi10_get_smu_metrics_data(smu, - METRICS_AVERAGE_SOCKETPOWER, - value); -} - -static int navi10_get_current_activity_percent(struct smu_context *smu, - enum amd_pp_sensors sensor, - uint32_t *value) -{ - int ret = 0; - - if (!value) - return -EINVAL; - - switch (sensor) { - case AMDGPU_PP_SENSOR_GPU_LOAD: - ret = navi10_get_smu_metrics_data(smu, - METRICS_AVERAGE_GFXACTIVITY, - value); - break; - case AMDGPU_PP_SENSOR_MEM_LOAD: - ret = navi10_get_smu_metrics_data(smu, - METRICS_AVERAGE_MEMACTIVITY, - value); - break; - default: - dev_err(smu->adev->dev, "Invalid sensor for retrieving clock activity\n"); - return -EINVAL; - } - - return ret; -} - static bool navi10_is_dpm_running(struct smu_context *smu) { int ret = 0; @@ -1652,39 +1614,6 @@ static int navi10_set_watermarks_table(struct smu_context *smu, return 0; } -static int navi10_thermal_get_temperature(struct smu_context *smu, - enum amd_pp_sensors sensor, - uint32_t *value) -{ - int ret = 0; - - if (!value) - return -EINVAL; - - switch (sensor) { - case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: - ret = navi10_get_smu_metrics_data(smu, - METRICS_TEMPERATURE_HOTSPOT, - value); - break; - case AMDGPU_PP_SENSOR_EDGE_TEMP: - ret = navi10_get_smu_metrics_data(smu, - METRICS_TEMPERATURE_EDGE, - value); - break; - case AMDGPU_PP_SENSOR_MEM_TEMP: - ret = navi10_get_smu_metrics_data(smu, - METRICS_TEMPERATURE_MEM, - value); - break; - default: - dev_err(smu->adev->dev, "Invalid sensor for retrieving temp\n"); - return -EINVAL; - } - - return ret; -} - static int navi10_read_sensor(struct smu_context *smu, enum amd_pp_sensors sensor, void *data, uint32_t *size) @@ -1703,18 +1632,39 @@ static int navi10_read_sensor(struct smu_context *smu, *size = 4; break; case AMDGPU_PP_SENSOR_MEM_LOAD: + ret = navi10_get_smu_metrics_data(smu, + METRICS_AVERAGE_MEMACTIVITY, + (uint32_t *)data); + *size = 4; + break; case AMDGPU_PP_SENSOR_GPU_LOAD: - ret = navi10_get_current_activity_percent(smu, sensor, (uint32_t *)data); + ret = navi10_get_smu_metrics_data(smu, + METRICS_AVERAGE_GFXACTIVITY, + (uint32_t *)data); *size = 4; break; case AMDGPU_PP_SENSOR_GPU_POWER: - ret = navi10_get_gpu_power(smu, (uint32_t *)data); + ret = navi10_get_smu_metrics_data(smu, + METRICS_AVERAGE_SOCKETPOWER, + (uint32_t *)data); *size = 4; break; case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: + ret = navi10_get_smu_metrics_data(smu, + METRICS_TEMPERATURE_HOTSPOT, + (uint32_t *)data); + *size = 4; + break; case AMDGPU_PP_SENSOR_EDGE_TEMP: + ret = navi10_get_smu_metrics_data(smu, + METRICS_TEMPERATURE_EDGE, + (uint32_t *)data); + *size = 4; + break; case AMDGPU_PP_SENSOR_MEM_TEMP: - ret = navi10_thermal_get_temperature(smu, sensor, (uint32_t *)data); + ret = navi10_get_smu_metrics_data(smu, + METRICS_TEMPERATURE_MEM, + (uint32_t *)data); *size = 4; break; case AMDGPU_PP_SENSOR_GFX_MCLK: @@ -2325,210 +2275,6 @@ static int navi10_run_umc_cdr_workaround(struct smu_context *smu) return 0; } -static void navi10_fill_i2c_req(SwI2cRequest_t *req, bool write, - uint8_t address, uint32_t numbytes, - uint8_t *data) -{ - int i; - - req->I2CcontrollerPort = 0; - req->I2CSpeed = 2; - req->SlaveAddress = address; - req->NumCmds = numbytes; - - for (i = 0; i < numbytes; i++) { - SwI2cCmd_t *cmd = &req->SwI2cCmds[i]; - - /* First 2 bytes are always write for lower 2b EEPROM address */ - if (i < 2) - cmd->Cmd = 1; - else - cmd->Cmd = write; - - - /* Add RESTART for read after address filled */ - cmd->CmdConfig |= (i == 2 && !write) ? CMDCONFIG_RESTART_MASK : 0; - - /* Add STOP in the end */ - cmd->CmdConfig |= (i == (numbytes - 1)) ? CMDCONFIG_STOP_MASK : 0; - - /* Fill with data regardless if read or write to simplify code */ - cmd->RegisterAddr = data[i]; - } -} - -static int navi10_i2c_read_data(struct i2c_adapter *control, - uint8_t address, - uint8_t *data, - uint32_t numbytes) -{ - uint32_t i, ret = 0; - SwI2cRequest_t req; - struct amdgpu_device *adev = to_amdgpu_device(control); - struct smu_table_context *smu_table = &adev->smu.smu_table; - struct smu_table *table = &smu_table->driver_table; - - if (numbytes > MAX_SW_I2C_COMMANDS) { - dev_err(adev->dev, "numbytes requested %d is over max allowed %d\n", - numbytes, MAX_SW_I2C_COMMANDS); - return -EINVAL; - } - - memset(&req, 0, sizeof(req)); - navi10_fill_i2c_req(&req, false, address, numbytes, data); - - mutex_lock(&adev->smu.mutex); - /* Now read data starting with that address */ - ret = smu_cmn_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, &req, - true); - mutex_unlock(&adev->smu.mutex); - - if (!ret) { - SwI2cRequest_t *res = (SwI2cRequest_t *)table->cpu_addr; - - /* Assume SMU fills res.SwI2cCmds[i].Data with read bytes */ - for (i = 0; i < numbytes; i++) - data[i] = res->SwI2cCmds[i].Data; - - dev_dbg(adev->dev, "navi10_i2c_read_data, address = %x, bytes = %d, data :", - (uint16_t)address, numbytes); - - print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE, - 8, 1, data, numbytes, false); - } else - dev_err(adev->dev, "navi10_i2c_read_data - error occurred :%x", ret); - - return ret; -} - -static int navi10_i2c_write_data(struct i2c_adapter *control, - uint8_t address, - uint8_t *data, - uint32_t numbytes) -{ - uint32_t ret; - SwI2cRequest_t req; - struct amdgpu_device *adev = to_amdgpu_device(control); - - if (numbytes > MAX_SW_I2C_COMMANDS) { - dev_err(adev->dev, "numbytes requested %d is over max allowed %d\n", - numbytes, MAX_SW_I2C_COMMANDS); - return -EINVAL; - } - - memset(&req, 0, sizeof(req)); - navi10_fill_i2c_req(&req, true, address, numbytes, data); - - mutex_lock(&adev->smu.mutex); - ret = smu_cmn_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, &req, true); - mutex_unlock(&adev->smu.mutex); - - if (!ret) { - dev_dbg(adev->dev, "navi10_i2c_write(), address = %x, bytes = %d , data: ", - (uint16_t)address, numbytes); - - print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE, - 8, 1, data, numbytes, false); - /* - * According to EEPROM spec there is a MAX of 10 ms required for - * EEPROM to flush internal RX buffer after STOP was issued at the - * end of write transaction. During this time the EEPROM will not be - * responsive to any more commands - so wait a bit more. - */ - msleep(10); - - } else - dev_err(adev->dev, "navi10_i2c_write- error occurred :%x", ret); - - return ret; -} - -static int navi10_i2c_xfer(struct i2c_adapter *i2c_adap, - struct i2c_msg *msgs, int num) -{ - uint32_t i, j, ret, data_size, data_chunk_size, next_eeprom_addr = 0; - uint8_t *data_ptr, data_chunk[MAX_SW_I2C_COMMANDS] = { 0 }; - - for (i = 0; i < num; i++) { - /* - * SMU interface allows at most MAX_SW_I2C_COMMANDS bytes of data at - * once and hence the data needs to be spliced into chunks and sent each - * chunk separately - */ - data_size = msgs[i].len - 2; - data_chunk_size = MAX_SW_I2C_COMMANDS - 2; - next_eeprom_addr = (msgs[i].buf[0] << 8 & 0xff00) | (msgs[i].buf[1] & 0xff); - data_ptr = msgs[i].buf + 2; - - for (j = 0; j < data_size / data_chunk_size; j++) { - /* Insert the EEPROM dest addess, bits 0-15 */ - data_chunk[0] = ((next_eeprom_addr >> 8) & 0xff); - data_chunk[1] = (next_eeprom_addr & 0xff); - - if (msgs[i].flags & I2C_M_RD) { - ret = navi10_i2c_read_data(i2c_adap, - (uint8_t)msgs[i].addr, - data_chunk, MAX_SW_I2C_COMMANDS); - - memcpy(data_ptr, data_chunk + 2, data_chunk_size); - } else { - - memcpy(data_chunk + 2, data_ptr, data_chunk_size); - - ret = navi10_i2c_write_data(i2c_adap, - (uint8_t)msgs[i].addr, - data_chunk, MAX_SW_I2C_COMMANDS); - } - - if (ret) { - num = -EIO; - goto fail; - } - - next_eeprom_addr += data_chunk_size; - data_ptr += data_chunk_size; - } - - if (data_size % data_chunk_size) { - data_chunk[0] = ((next_eeprom_addr >> 8) & 0xff); - data_chunk[1] = (next_eeprom_addr & 0xff); - - if (msgs[i].flags & I2C_M_RD) { - ret = navi10_i2c_read_data(i2c_adap, - (uint8_t)msgs[i].addr, - data_chunk, (data_size % data_chunk_size) + 2); - - memcpy(data_ptr, data_chunk + 2, data_size % data_chunk_size); - } else { - memcpy(data_chunk + 2, data_ptr, data_size % data_chunk_size); - - ret = navi10_i2c_write_data(i2c_adap, - (uint8_t)msgs[i].addr, - data_chunk, (data_size % data_chunk_size) + 2); - } - - if (ret) { - num = -EIO; - goto fail; - } - } - } - -fail: - return num; -} - -static u32 navi10_i2c_func(struct i2c_adapter *adap) -{ - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; -} - - -static const struct i2c_algorithm navi10_i2c_algo = { - .master_xfer = navi10_i2c_xfer, - .functionality = navi10_i2c_func, -}; - static ssize_t navi10_get_gpu_metrics(struct smu_context *smu, void **table) { diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index 0600befc6e4c..db0f2a476c23 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -1119,44 +1119,6 @@ static int sienna_cichlid_display_config_changed(struct smu_context *smu) return ret; } -static int sienna_cichlid_get_gpu_power(struct smu_context *smu, uint32_t *value) -{ - if (!value) - return -EINVAL; - - return sienna_cichlid_get_smu_metrics_data(smu, - METRICS_AVERAGE_SOCKETPOWER, - value); -} - -static int sienna_cichlid_get_current_activity_percent(struct smu_context *smu, - enum amd_pp_sensors sensor, - uint32_t *value) -{ - int ret = 0; - - if (!value) - return -EINVAL; - - switch (sensor) { - case AMDGPU_PP_SENSOR_GPU_LOAD: - ret = sienna_cichlid_get_smu_metrics_data(smu, - METRICS_AVERAGE_GFXACTIVITY, - value); - break; - case AMDGPU_PP_SENSOR_MEM_LOAD: - ret = sienna_cichlid_get_smu_metrics_data(smu, - METRICS_AVERAGE_MEMACTIVITY, - value); - break; - default: - dev_err(smu->adev->dev, "Invalid sensor for retrieving clock activity\n"); - return -EINVAL; - } - - return ret; -} - static bool sienna_cichlid_is_dpm_running(struct smu_context *smu) { int ret = 0; @@ -1468,39 +1430,6 @@ static int sienna_cichlid_set_watermarks_table(struct smu_context *smu, return 0; } -static int sienna_cichlid_thermal_get_temperature(struct smu_context *smu, - enum amd_pp_sensors sensor, - uint32_t *value) -{ - int ret = 0; - - if (!value) - return -EINVAL; - - switch (sensor) { - case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: - ret = sienna_cichlid_get_smu_metrics_data(smu, - METRICS_TEMPERATURE_HOTSPOT, - value); - break; - case AMDGPU_PP_SENSOR_EDGE_TEMP: - ret = sienna_cichlid_get_smu_metrics_data(smu, - METRICS_TEMPERATURE_EDGE, - value); - break; - case AMDGPU_PP_SENSOR_MEM_TEMP: - ret = sienna_cichlid_get_smu_metrics_data(smu, - METRICS_TEMPERATURE_MEM, - value); - break; - default: - dev_err(smu->adev->dev, "Invalid sensor for retrieving temp\n"); - return -EINVAL; - } - - return ret; -} - static int sienna_cichlid_read_sensor(struct smu_context *smu, enum amd_pp_sensors sensor, void *data, uint32_t *size) @@ -1519,18 +1448,39 @@ static int sienna_cichlid_read_sensor(struct smu_context *smu, *size = 4; break; case AMDGPU_PP_SENSOR_MEM_LOAD: + ret = sienna_cichlid_get_smu_metrics_data(smu, + METRICS_AVERAGE_MEMACTIVITY, + (uint32_t *)data); + *size = 4; + break; case AMDGPU_PP_SENSOR_GPU_LOAD: - ret = sienna_cichlid_get_current_activity_percent(smu, sensor, (uint32_t *)data); + ret = sienna_cichlid_get_smu_metrics_data(smu, + METRICS_AVERAGE_GFXACTIVITY, + (uint32_t *)data); *size = 4; break; case AMDGPU_PP_SENSOR_GPU_POWER: - ret = sienna_cichlid_get_gpu_power(smu, (uint32_t *)data); + ret = sienna_cichlid_get_smu_metrics_data(smu, + METRICS_AVERAGE_SOCKETPOWER, + (uint32_t *)data); *size = 4; break; case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: + ret = sienna_cichlid_get_smu_metrics_data(smu, + METRICS_TEMPERATURE_HOTSPOT, + (uint32_t *)data); + *size = 4; + break; case AMDGPU_PP_SENSOR_EDGE_TEMP: + ret = sienna_cichlid_get_smu_metrics_data(smu, + METRICS_TEMPERATURE_EDGE, + (uint32_t *)data); + *size = 4; + break; case AMDGPU_PP_SENSOR_MEM_TEMP: - ret = sienna_cichlid_thermal_get_temperature(smu, sensor, (uint32_t *)data); + ret = sienna_cichlid_get_smu_metrics_data(smu, + METRICS_TEMPERATURE_MEM, + (uint32_t *)data); *size = 4; break; case AMDGPU_PP_SENSOR_GFX_MCLK: @@ -1805,11 +1755,6 @@ static void sienna_cichlid_dump_pptable(struct smu_context *smu) dev_info(smu->adev->dev, "SmnclkDpmFreq[%d] = 0x%x\n", i, pptable->SmnclkDpmFreq[i]); dev_info(smu->adev->dev, "SmnclkDpmVoltage[%d] = 0x%x\n", i, pptable->SmnclkDpmVoltage[i]); } - dev_info(smu->adev->dev, "PaddingAPCC[0] = 0x%x\n", pptable->PaddingAPCC[0]); - dev_info(smu->adev->dev, "PaddingAPCC[1] = 0x%x\n", pptable->PaddingAPCC[1]); - dev_info(smu->adev->dev, "PaddingAPCC[2] = 0x%x\n", pptable->PaddingAPCC[2]); - dev_info(smu->adev->dev, "PaddingAPCC[3] = 0x%x\n", pptable->PaddingAPCC[3]); - dev_info(smu->adev->dev, "ThrottlerControlMask = 0x%x\n", pptable->ThrottlerControlMask); dev_info(smu->adev->dev, "FwDStateMask = 0x%x\n", pptable->FwDStateMask); @@ -2036,23 +1981,6 @@ static void sienna_cichlid_dump_pptable(struct smu_context *smu) for (i = 0; i < NUM_FCLK_DPM_LEVELS; i++) dev_info(smu->adev->dev, " .[%02d] = 0x%x\n", i, pptable->FreqTableFclk[i]); - dev_info(smu->adev->dev, "Paddingclks[0] = 0x%x\n", pptable->Paddingclks[0]); - dev_info(smu->adev->dev, "Paddingclks[1] = 0x%x\n", pptable->Paddingclks[1]); - dev_info(smu->adev->dev, "Paddingclks[2] = 0x%x\n", pptable->Paddingclks[2]); - dev_info(smu->adev->dev, "Paddingclks[3] = 0x%x\n", pptable->Paddingclks[3]); - dev_info(smu->adev->dev, "Paddingclks[4] = 0x%x\n", pptable->Paddingclks[4]); - dev_info(smu->adev->dev, "Paddingclks[5] = 0x%x\n", pptable->Paddingclks[5]); - dev_info(smu->adev->dev, "Paddingclks[6] = 0x%x\n", pptable->Paddingclks[6]); - dev_info(smu->adev->dev, "Paddingclks[7] = 0x%x\n", pptable->Paddingclks[7]); - dev_info(smu->adev->dev, "Paddingclks[8] = 0x%x\n", pptable->Paddingclks[8]); - dev_info(smu->adev->dev, "Paddingclks[9] = 0x%x\n", pptable->Paddingclks[9]); - dev_info(smu->adev->dev, "Paddingclks[10] = 0x%x\n", pptable->Paddingclks[10]); - dev_info(smu->adev->dev, "Paddingclks[11] = 0x%x\n", pptable->Paddingclks[11]); - dev_info(smu->adev->dev, "Paddingclks[12] = 0x%x\n", pptable->Paddingclks[12]); - dev_info(smu->adev->dev, "Paddingclks[13] = 0x%x\n", pptable->Paddingclks[13]); - dev_info(smu->adev->dev, "Paddingclks[14] = 0x%x\n", pptable->Paddingclks[14]); - dev_info(smu->adev->dev, "Paddingclks[15] = 0x%x\n", pptable->Paddingclks[15]); - dev_info(smu->adev->dev, "DcModeMaxFreq\n"); dev_info(smu->adev->dev, " .PPCLK_GFXCLK = 0x%x\n", pptable->DcModeMaxFreq[PPCLK_GFXCLK]); dev_info(smu->adev->dev, " .PPCLK_SOCCLK = 0x%x\n", pptable->DcModeMaxFreq[PPCLK_SOCCLK]); diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c index b6453ee6f8e6..624065d3c079 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c @@ -216,6 +216,7 @@ int smu_v11_0_check_fw_status(struct smu_context *smu) int smu_v11_0_check_fw_version(struct smu_context *smu) { + struct amdgpu_device *adev = smu->adev; uint32_t if_version = 0xff, smu_version = 0xff; uint16_t smu_major; uint8_t smu_minor, smu_debug; @@ -228,6 +229,8 @@ int smu_v11_0_check_fw_version(struct smu_context *smu) smu_major = (smu_version >> 16) & 0xffff; smu_minor = (smu_version >> 8) & 0xff; smu_debug = (smu_version >> 0) & 0xff; + if (smu->is_apu) + adev->pm.fw_version = smu_version; switch (smu->adev->asic_type) { case CHIP_ARCTURUS: @@ -336,8 +339,7 @@ int smu_v11_0_setup_pptable(struct smu_context *smu) hdr = (const struct smc_firmware_header_v1_0 *) adev->pm.fw->data; version_major = le16_to_cpu(hdr->header.header_version_major); version_minor = le16_to_cpu(hdr->header.header_version_minor); - if ((version_major == 2 && smu->smu_table.boot_values.pp_table_id > 0) || - adev->asic_type == CHIP_DIMGREY_CAVEFISH) { + if (version_major == 2 && smu->smu_table.boot_values.pp_table_id > 0) { dev_info(adev->dev, "use driver provided pptable %d\n", smu->smu_table.boot_values.pp_table_id); switch (version_minor) { case 0: @@ -435,11 +437,13 @@ int smu_v11_0_fini_smc_tables(struct smu_context *smu) kfree(smu_table->overdrive_table); kfree(smu_table->max_sustainable_clocks); kfree(smu_table->driver_pptable); + kfree(smu_table->clocks_table); smu_table->gpu_metrics_table = NULL; smu_table->boot_overdrive_table = NULL; smu_table->overdrive_table = NULL; smu_table->max_sustainable_clocks = NULL; smu_table->driver_pptable = NULL; + smu_table->clocks_table = NULL; kfree(smu_table->hardcode_pptable); smu_table->hardcode_pptable = NULL; @@ -466,11 +470,11 @@ int smu_v11_0_init_power(struct smu_context *smu) { struct smu_power_context *smu_power = &smu->smu_power; - smu_power->power_context = kzalloc(sizeof(struct smu_11_0_dpm_context), + smu_power->power_context = kzalloc(sizeof(struct smu_11_0_power_context), GFP_KERNEL); if (!smu_power->power_context) return -ENOMEM; - smu_power->power_context_size = sizeof(struct smu_11_0_dpm_context); + smu_power->power_context_size = sizeof(struct smu_11_0_power_context); return 0; } @@ -1183,7 +1187,12 @@ int smu_v11_0_set_fan_speed_rpm(struct smu_context *smu, if (ret) return ret; - crystal_clock_freq = amdgpu_asic_get_xclk(adev); + /* + * crystal_clock_freq div by 4 is required since the fan control + * module refers to 25MHz + */ + + crystal_clock_freq = amdgpu_asic_get_xclk(adev) / 4; tach_period = 60 * crystal_clock_freq * 10000 / (8 * speed); WREG32_SOC15(THM, 0, mmCG_TACH_CTRL, REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_TACH_CTRL), @@ -1481,6 +1490,9 @@ enum smu_baco_state smu_v11_0_baco_get_state(struct smu_context *smu) return baco_state; } +#define D3HOT_BACO_SEQUENCE 0 +#define D3HOT_BAMACO_SEQUENCE 2 + int smu_v11_0_baco_set_state(struct smu_context *smu, enum smu_baco_state state) { struct smu_baco_context *smu_baco = &smu->smu_baco; @@ -1495,15 +1507,34 @@ int smu_v11_0_baco_set_state(struct smu_context *smu, enum smu_baco_state state) mutex_lock(&smu_baco->mutex); if (state == SMU_BACO_STATE_ENTER) { - if (!ras || !ras->supported) { - data = RREG32_SOC15(THM, 0, mmTHM_BACO_CNTL); - data |= 0x80000000; - WREG32_SOC15(THM, 0, mmTHM_BACO_CNTL, data); - - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_EnterBaco, 0, NULL); - } else { - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_EnterBaco, 1, NULL); + switch (adev->asic_type) { + case CHIP_SIENNA_CICHLID: + case CHIP_NAVY_FLOUNDER: + case CHIP_DIMGREY_CAVEFISH: + if (amdgpu_runtime_pm == 2) + ret = smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_EnterBaco, + D3HOT_BAMACO_SEQUENCE, + NULL); + else + ret = smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_EnterBaco, + D3HOT_BACO_SEQUENCE, + NULL); + break; + default: + if (!ras || !ras->supported) { + data = RREG32_SOC15(THM, 0, mmTHM_BACO_CNTL); + data |= 0x80000000; + WREG32_SOC15(THM, 0, mmTHM_BACO_CNTL, data); + + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_EnterBaco, 0, NULL); + } else { + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_EnterBaco, 1, NULL); + } + break; } + } else { ret = smu_cmn_send_smc_msg(smu, SMU_MSG_ExitBaco, NULL); if (ret) @@ -1996,6 +2027,18 @@ void smu_v11_0_init_gpu_metrics_v1_0(struct gpu_metrics_v1_0 *gpu_metrics) gpu_metrics->system_clock_counter = ktime_get_boottime_ns(); } +void smu_v11_0_init_gpu_metrics_v2_0(struct gpu_metrics_v2_0 *gpu_metrics) +{ + memset(gpu_metrics, 0xFF, sizeof(struct gpu_metrics_v2_0)); + + gpu_metrics->common_header.structure_size = + sizeof(struct gpu_metrics_v2_0); + gpu_metrics->common_header.format_revision = 2; + gpu_metrics->common_header.content_revision = 0; + + gpu_metrics->system_clock_counter = ktime_get_boottime_ns(); +} + int smu_v11_0_gfx_ulv_control(struct smu_context *smu, bool enablement) { diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c index 83a1b0a04eb1..a81e5c823211 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c @@ -200,8 +200,14 @@ static int vangogh_tables_init(struct smu_context *smu) if (!smu_table->watermarks_table) goto err2_out; + smu_table->clocks_table = kzalloc(sizeof(DpmClocks_t), GFP_KERNEL); + if (!smu_table->clocks_table) + goto err3_out; + return 0; +err3_out: + kfree(smu_table->clocks_table); err2_out: kfree(smu_table->gpu_metrics_table); err1_out: @@ -259,6 +265,12 @@ static int vangogh_get_smu_metrics_data(struct smu_context *smu, case METRICS_THROTTLER_STATUS: *value = metrics->ThrottlerStatus; break; + case METRICS_VOLTAGE_VDDGFX: + *value = metrics->Voltage[2]; + break; + case METRICS_VOLTAGE_VDDSOC: + *value = metrics->Voltage[1]; + break; default: *value = UINT_MAX; break; @@ -390,91 +402,33 @@ static bool vangogh_is_dpm_running(struct smu_context *smu) return !!(feature_enabled & SMC_DPM_FEATURE); } -static int vangogh_get_current_activity_percent(struct smu_context *smu, - enum amd_pp_sensors sensor, - uint32_t *value) -{ - int ret = 0; - - if (!value) - return -EINVAL; - - switch (sensor) { - case AMDGPU_PP_SENSOR_GPU_LOAD: - ret = vangogh_get_smu_metrics_data(smu, - METRICS_AVERAGE_GFXACTIVITY, - value); - break; - default: - dev_err(smu->adev->dev, "Invalid sensor for retrieving clock activity\n"); - return -EINVAL; - } - - return 0; -} - -static int vangogh_get_gpu_power(struct smu_context *smu, uint32_t *value) -{ - if (!value) - return -EINVAL; - - return vangogh_get_smu_metrics_data(smu, - METRICS_AVERAGE_SOCKETPOWER, - value); -} - -static int vangogh_thermal_get_temperature(struct smu_context *smu, - enum amd_pp_sensors sensor, - uint32_t *value) -{ - int ret = 0; - - if (!value) - return -EINVAL; - - switch (sensor) { - case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: - ret = vangogh_get_smu_metrics_data(smu, - METRICS_TEMPERATURE_HOTSPOT, - value); - break; - case AMDGPU_PP_SENSOR_EDGE_TEMP: - ret = vangogh_get_smu_metrics_data(smu, - METRICS_TEMPERATURE_EDGE, - value); - break; - default: - dev_err(smu->adev->dev, "Invalid sensor for retrieving temp\n"); - return -EINVAL; - } - - return ret; -} - -static int vangogh_get_current_clk_freq_by_table(struct smu_context *smu, - enum smu_clk_type clk_type, - uint32_t *value) +static int vangogh_print_fine_grain_clk(struct smu_context *smu, + enum smu_clk_type clk_type, char *buf) { - MetricsMember_t member_type; + int size = 0; switch (clk_type) { - case SMU_GFXCLK: - member_type = METRICS_AVERAGE_GFXCLK; - break; - case SMU_MCLK: - case SMU_UCLK: - member_type = METRICS_AVERAGE_UCLK; + case SMU_OD_SCLK: + if (smu->od_enabled) { + size = sprintf(buf, "%s:\n", "OD_SCLK"); + size += sprintf(buf + size, "0: %10uMhz\n", + (smu->gfx_actual_hard_min_freq > 0) ? smu->gfx_actual_hard_min_freq : smu->gfx_default_hard_min_freq); + size += sprintf(buf + size, "1: %10uMhz\n", + (smu->gfx_actual_soft_max_freq > 0) ? smu->gfx_actual_soft_max_freq : smu->gfx_default_soft_max_freq); + } break; - case SMU_SOCCLK: - member_type = METRICS_AVERAGE_SOCCLK; + case SMU_OD_RANGE: + if (smu->od_enabled) { + size = sprintf(buf, "%s:\n", "OD_RANGE"); + size += sprintf(buf + size, "SCLK: %7uMhz %10uMhz\n", + smu->gfx_default_hard_min_freq, smu->gfx_default_soft_max_freq); + } break; default: - return -EINVAL; + break; } - return vangogh_get_smu_metrics_data(smu, - member_type, - value); + return size; } static int vangogh_read_sensor(struct smu_context *smu, @@ -489,30 +443,53 @@ static int vangogh_read_sensor(struct smu_context *smu, mutex_lock(&smu->sensor_lock); switch (sensor) { case AMDGPU_PP_SENSOR_GPU_LOAD: - ret = vangogh_get_current_activity_percent(smu, sensor, (uint32_t *)data); + ret = vangogh_get_smu_metrics_data(smu, + METRICS_AVERAGE_GFXACTIVITY, + (uint32_t *)data); *size = 4; break; case AMDGPU_PP_SENSOR_GPU_POWER: - ret = vangogh_get_gpu_power(smu, (uint32_t *)data); + ret = vangogh_get_smu_metrics_data(smu, + METRICS_AVERAGE_SOCKETPOWER, + (uint32_t *)data); *size = 4; break; case AMDGPU_PP_SENSOR_EDGE_TEMP: + ret = vangogh_get_smu_metrics_data(smu, + METRICS_TEMPERATURE_EDGE, + (uint32_t *)data); + *size = 4; + break; case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: - ret = vangogh_thermal_get_temperature(smu, sensor, (uint32_t *)data); + ret = vangogh_get_smu_metrics_data(smu, + METRICS_TEMPERATURE_HOTSPOT, + (uint32_t *)data); *size = 4; break; case AMDGPU_PP_SENSOR_GFX_MCLK: - ret = vangogh_get_current_clk_freq_by_table(smu, SMU_UCLK, (uint32_t *)data); + ret = vangogh_get_smu_metrics_data(smu, + METRICS_AVERAGE_UCLK, + (uint32_t *)data); *(uint32_t *)data *= 100; *size = 4; break; case AMDGPU_PP_SENSOR_GFX_SCLK: - ret = vangogh_get_current_clk_freq_by_table(smu, SMU_GFXCLK, (uint32_t *)data); + ret = vangogh_get_smu_metrics_data(smu, + METRICS_AVERAGE_GFXCLK, + (uint32_t *)data); *(uint32_t *)data *= 100; *size = 4; break; case AMDGPU_PP_SENSOR_VDDGFX: - ret = smu_v11_0_get_gfx_vdd(smu, (uint32_t *)data); + ret = vangogh_get_smu_metrics_data(smu, + METRICS_VOLTAGE_VDDGFX, + (uint32_t *)data); + *size = 4; + break; + case AMDGPU_PP_SENSOR_VDDNB: + ret = vangogh_get_smu_metrics_data(smu, + METRICS_VOLTAGE_VDDSOC, + (uint32_t *)data); *size = 4; break; default: @@ -584,6 +561,167 @@ static int vangogh_set_watermarks_table(struct smu_context *smu, return 0; } +static ssize_t vangogh_get_gpu_metrics(struct smu_context *smu, + void **table) +{ + struct smu_table_context *smu_table = &smu->smu_table; + struct gpu_metrics_v2_0 *gpu_metrics = + (struct gpu_metrics_v2_0 *)smu_table->gpu_metrics_table; + SmuMetrics_t metrics; + int ret = 0; + + ret = smu_cmn_get_metrics_table(smu, &metrics, true); + if (ret) + return ret; + + smu_v11_0_init_gpu_metrics_v2_0(gpu_metrics); + + gpu_metrics->temperature_gfx = metrics.GfxTemperature; + gpu_metrics->temperature_soc = metrics.SocTemperature; + memcpy(&gpu_metrics->temperature_core[0], + &metrics.CoreTemperature[0], + sizeof(uint16_t) * 8); + gpu_metrics->temperature_l3[0] = metrics.L3Temperature[0]; + gpu_metrics->temperature_l3[1] = metrics.L3Temperature[1]; + + gpu_metrics->average_gfx_activity = metrics.GfxActivity; + gpu_metrics->average_mm_activity = metrics.UvdActivity; + + gpu_metrics->average_socket_power = metrics.CurrentSocketPower; + gpu_metrics->average_cpu_power = metrics.Power[0]; + gpu_metrics->average_soc_power = metrics.Power[1]; + memcpy(&gpu_metrics->average_core_power[0], + &metrics.CorePower[0], + sizeof(uint16_t) * 8); + + gpu_metrics->average_gfxclk_frequency = metrics.GfxclkFrequency; + gpu_metrics->average_socclk_frequency = metrics.SocclkFrequency; + gpu_metrics->average_fclk_frequency = metrics.MemclkFrequency; + gpu_metrics->average_vclk_frequency = metrics.VclkFrequency; + + memcpy(&gpu_metrics->current_coreclk[0], + &metrics.CoreFrequency[0], + sizeof(uint16_t) * 8); + gpu_metrics->current_l3clk[0] = metrics.L3Frequency[0]; + gpu_metrics->current_l3clk[1] = metrics.L3Frequency[1]; + + gpu_metrics->throttle_status = metrics.ThrottlerStatus; + + *table = (void *)gpu_metrics; + + return sizeof(struct gpu_metrics_v2_0); +} + +static int vangogh_od_edit_dpm_table(struct smu_context *smu, enum PP_OD_DPM_TABLE_COMMAND type, + long input[], uint32_t size) +{ + int ret = 0; + + if (!smu->od_enabled) { + dev_warn(smu->adev->dev, "Fine grain is not enabled!\n"); + return -EINVAL; + } + + switch (type) { + case PP_OD_EDIT_SCLK_VDDC_TABLE: + if (size != 2) { + dev_err(smu->adev->dev, "Input parameter number not correct\n"); + return -EINVAL; + } + + if (input[0] == 0) { + if (input[1] < smu->gfx_default_hard_min_freq) { + dev_warn(smu->adev->dev, "Fine grain setting minimum sclk (%ld) MHz is less than the minimum allowed (%d) MHz\n", + input[1], smu->gfx_default_hard_min_freq); + return -EINVAL; + } + smu->gfx_actual_hard_min_freq = input[1]; + } else if (input[0] == 1) { + if (input[1] > smu->gfx_default_soft_max_freq) { + dev_warn(smu->adev->dev, "Fine grain setting maximum sclk (%ld) MHz is greater than the maximum allowed (%d) MHz\n", + input[1], smu->gfx_default_soft_max_freq); + return -EINVAL; + } + smu->gfx_actual_soft_max_freq = input[1]; + } else { + return -EINVAL; + } + break; + case PP_OD_RESTORE_DEFAULT_TABLE: + if (size != 0) { + dev_err(smu->adev->dev, "Input parameter number not correct\n"); + return -EINVAL; + } else { + smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq; + smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq; + + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinGfxClk, + smu->gfx_actual_hard_min_freq, NULL); + if (ret) { + dev_err(smu->adev->dev, "Restore the default hard min sclk failed!"); + return ret; + } + + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk, + smu->gfx_actual_soft_max_freq, NULL); + if (ret) { + dev_err(smu->adev->dev, "Restore the default soft max sclk failed!"); + return ret; + } + } + break; + case PP_OD_COMMIT_DPM_TABLE: + if (size != 0) { + dev_err(smu->adev->dev, "Input parameter number not correct\n"); + return -EINVAL; + } else { + if (smu->gfx_actual_hard_min_freq > smu->gfx_actual_soft_max_freq) { + dev_err(smu->adev->dev, "The setting minimun sclk (%d) MHz is greater than the setting maximum sclk (%d) MHz\n", + smu->gfx_actual_hard_min_freq, smu->gfx_actual_soft_max_freq); + return -EINVAL; + } + + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinGfxClk, + smu->gfx_actual_hard_min_freq, NULL); + if (ret) { + dev_err(smu->adev->dev, "Set hard min sclk failed!"); + return ret; + } + + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk, + smu->gfx_actual_soft_max_freq, NULL); + if (ret) { + dev_err(smu->adev->dev, "Set soft max sclk failed!"); + return ret; + } + } + break; + default: + return -ENOSYS; + } + + return ret; +} + +static int vangogh_set_default_dpm_tables(struct smu_context *smu) +{ + struct smu_table_context *smu_table = &smu->smu_table; + + return smu_cmn_update_table(smu, SMU_TABLE_DPMCLOCKS, 0, smu_table->clocks_table, false); +} + +static int vangogh_set_fine_grain_gfx_freq_parameters(struct smu_context *smu) +{ + DpmClocks_t *clk_table = smu->smu_table.clocks_table; + + smu->gfx_default_hard_min_freq = clk_table->MinGfxClk; + smu->gfx_default_soft_max_freq = clk_table->MaxGfxClk; + smu->gfx_actual_hard_min_freq = 0; + smu->gfx_actual_soft_max_freq = 0; + + return 0; +} + static const struct pptable_funcs vangogh_ppt_funcs = { .check_fw_status = smu_v11_0_check_fw_status, @@ -605,8 +743,12 @@ static const struct pptable_funcs vangogh_ppt_funcs = { .get_pp_feature_mask = smu_cmn_get_pp_feature_mask, .set_watermarks_table = vangogh_set_watermarks_table, .set_driver_table_location = smu_v11_0_set_driver_table_location, - .disable_all_features_with_exception = smu_cmn_disable_all_features_with_exception, .interrupt_work = smu_v11_0_interrupt_work, + .get_gpu_metrics = vangogh_get_gpu_metrics, + .od_edit_dpm_table = vangogh_od_edit_dpm_table, + .print_clk_levels = vangogh_print_fine_grain_clk, + .set_default_dpm_table = vangogh_set_default_dpm_tables, + .set_fine_grain_gfx_freq_parameters = vangogh_set_fine_grain_gfx_freq_parameters, }; void vangogh_set_ppt_funcs(struct smu_context *smu) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c index 66c1026489be..dc75db8af371 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c @@ -170,7 +170,7 @@ err0_out: return -ENOMEM; } -/** +/* * This interface just for getting uclk ultimate freq and should't introduce * other likewise function result in overmuch callback. */ @@ -492,28 +492,6 @@ static int renoir_dpm_set_jpeg_enable(struct smu_context *smu, bool enable) return ret; } -static int renoir_get_current_clk_freq_by_table(struct smu_context *smu, - enum smu_clk_type clk_type, - uint32_t *value) -{ - int ret = 0, clk_id = 0; - SmuMetrics_t metrics; - - ret = smu_cmn_get_metrics_table(smu, &metrics, false); - if (ret) - return ret; - - clk_id = smu_cmn_to_asic_specific_index(smu, - CMN2ASIC_MAPPING_CLK, - clk_type); - if (clk_id < 0) - return clk_id; - - *value = metrics.ClockFrequency[clk_id]; - - return ret; -} - static int renoir_force_dpm_limit_value(struct smu_context *smu, bool highest) { int ret = 0, i = 0; @@ -574,89 +552,7 @@ static int renoir_unforce_dpm_levels(struct smu_context *smu) { return ret; } -static int renoir_get_gpu_temperature(struct smu_context *smu, uint32_t *value) -{ - int ret = 0; - SmuMetrics_t metrics; - - if (!value) - return -EINVAL; - - ret = smu_cmn_get_metrics_table(smu, &metrics, false); - if (ret) - return ret; - - *value = (metrics.GfxTemperature / 100) * - SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; - - return 0; -} - -static int renoir_get_current_activity_percent(struct smu_context *smu, - enum amd_pp_sensors sensor, - uint32_t *value) -{ - int ret = 0; - SmuMetrics_t metrics; - - if (!value) - return -EINVAL; - - ret = smu_cmn_get_metrics_table(smu, &metrics, false); - if (ret) - return ret; - - switch (sensor) { - case AMDGPU_PP_SENSOR_GPU_LOAD: - *value = metrics.AverageGfxActivity / 100; - break; - default: - dev_err(smu->adev->dev, "Invalid sensor for retrieving clock activity\n"); - return -EINVAL; - } - - return 0; -} - -static int renoir_get_vddc(struct smu_context *smu, uint32_t *value, - unsigned int index) -{ - int ret = 0; - SmuMetrics_t metrics; - - if (index >= 2) - return -EINVAL; - - if (!value) - return -EINVAL; - - ret = smu_cmn_get_metrics_table(smu, &metrics, false); - if (ret) - return ret; - - *value = metrics.Voltage[index]; - - return 0; -} - -static int renoir_get_power(struct smu_context *smu, uint32_t *value) -{ - int ret = 0; - SmuMetrics_t metrics; - - if (!value) - return -EINVAL; - - ret = smu_cmn_get_metrics_table(smu, &metrics, false); - if (ret) - return ret; - - *value = metrics.CurrentSocketPower << 8; - - return 0; -} - -/** +/* * This interface get dpm clock table for dc */ static int renoir_get_dpm_clock_table(struct smu_context *smu, struct dpm_clocks *clock_table) @@ -1011,6 +907,71 @@ static int renoir_get_power_profile_mode(struct smu_context *smu, return size; } +static int renoir_get_smu_metrics_data(struct smu_context *smu, + MetricsMember_t member, + uint32_t *value) +{ + struct smu_table_context *smu_table = &smu->smu_table; + + SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table; + int ret = 0; + + mutex_lock(&smu->metrics_lock); + + ret = smu_cmn_get_metrics_table_locked(smu, + NULL, + false); + if (ret) { + mutex_unlock(&smu->metrics_lock); + return ret; + } + + switch (member) { + case METRICS_AVERAGE_GFXCLK: + *value = metrics->ClockFrequency[CLOCK_GFXCLK]; + break; + case METRICS_AVERAGE_SOCCLK: + *value = metrics->ClockFrequency[CLOCK_SOCCLK]; + break; + case METRICS_AVERAGE_UCLK: + *value = metrics->ClockFrequency[CLOCK_FCLK]; + break; + case METRICS_AVERAGE_GFXACTIVITY: + *value = metrics->AverageGfxActivity / 100; + break; + case METRICS_AVERAGE_VCNACTIVITY: + *value = metrics->AverageUvdActivity / 100; + break; + case METRICS_AVERAGE_SOCKETPOWER: + *value = metrics->CurrentSocketPower << 8; + break; + case METRICS_TEMPERATURE_EDGE: + *value = (metrics->GfxTemperature / 100) * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + break; + case METRICS_TEMPERATURE_HOTSPOT: + *value = (metrics->SocTemperature / 100) * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + break; + case METRICS_THROTTLER_STATUS: + *value = metrics->ThrottlerStatus; + break; + case METRICS_VOLTAGE_VDDGFX: + *value = metrics->Voltage[0]; + break; + case METRICS_VOLTAGE_VDDSOC: + *value = metrics->Voltage[1]; + break; + default: + *value = UINT_MAX; + break; + } + + mutex_unlock(&smu->metrics_lock); + + return ret; +} + static int renoir_read_sensor(struct smu_context *smu, enum amd_pp_sensors sensor, void *data, uint32_t *size) @@ -1023,33 +984,53 @@ static int renoir_read_sensor(struct smu_context *smu, mutex_lock(&smu->sensor_lock); switch (sensor) { case AMDGPU_PP_SENSOR_GPU_LOAD: - ret = renoir_get_current_activity_percent(smu, sensor, (uint32_t *)data); + ret = renoir_get_smu_metrics_data(smu, + METRICS_AVERAGE_GFXACTIVITY, + (uint32_t *)data); + *size = 4; + break; + case AMDGPU_PP_SENSOR_EDGE_TEMP: + ret = renoir_get_smu_metrics_data(smu, + METRICS_TEMPERATURE_EDGE, + (uint32_t *)data); *size = 4; break; - case AMDGPU_PP_SENSOR_GPU_TEMP: - ret = renoir_get_gpu_temperature(smu, (uint32_t *)data); + case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: + ret = renoir_get_smu_metrics_data(smu, + METRICS_TEMPERATURE_HOTSPOT, + (uint32_t *)data); *size = 4; break; case AMDGPU_PP_SENSOR_GFX_MCLK: - ret = renoir_get_current_clk_freq_by_table(smu, SMU_UCLK, (uint32_t *)data); + ret = renoir_get_smu_metrics_data(smu, + METRICS_AVERAGE_UCLK, + (uint32_t *)data); *(uint32_t *)data *= 100; *size = 4; break; case AMDGPU_PP_SENSOR_GFX_SCLK: - ret = renoir_get_current_clk_freq_by_table(smu, SMU_GFXCLK, (uint32_t *)data); + ret = renoir_get_smu_metrics_data(smu, + METRICS_AVERAGE_GFXCLK, + (uint32_t *)data); *(uint32_t *)data *= 100; *size = 4; break; case AMDGPU_PP_SENSOR_VDDGFX: - ret = renoir_get_vddc(smu, (uint32_t *)data, 0); + ret = renoir_get_smu_metrics_data(smu, + METRICS_VOLTAGE_VDDGFX, + (uint32_t *)data); *size = 4; break; case AMDGPU_PP_SENSOR_VDDNB: - ret = renoir_get_vddc(smu, (uint32_t *)data, 1); + ret = renoir_get_smu_metrics_data(smu, + METRICS_VOLTAGE_VDDSOC, + (uint32_t *)data); *size = 4; break; case AMDGPU_PP_SENSOR_GPU_POWER: - ret = renoir_get_power(smu, (uint32_t *)data); + ret = renoir_get_smu_metrics_data(smu, + METRICS_AVERAGE_SOCKETPOWER, + (uint32_t *)data); *size = 4; break; default: @@ -1136,6 +1117,12 @@ static ssize_t renoir_get_gpu_metrics(struct smu_context *smu, return sizeof(struct gpu_metrics_v2_0); } +static int renoir_gfx_state_change_set(struct smu_context *smu, uint32_t state) +{ + + return smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_GpuChangeState, state, NULL); +} + static const struct pptable_funcs renoir_ppt_funcs = { .set_power_state = NULL, .print_clk_levels = renoir_print_clk_levels, @@ -1171,6 +1158,7 @@ static const struct pptable_funcs renoir_ppt_funcs = { .get_pp_feature_mask = smu_cmn_get_pp_feature_mask, .set_pp_feature_mask = smu_cmn_set_pp_feature_mask, .get_gpu_metrics = renoir_get_gpu_metrics, + .gfx_state_change_set = renoir_gfx_state_change_set, }; void renoir_set_ppt_funcs(struct smu_context *smu) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu12/smu_v12_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu12/smu_v12_0.c index 660f403d5770..522d55004655 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu12/smu_v12_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu12/smu_v12_0.c @@ -71,6 +71,7 @@ int smu_v12_0_check_fw_status(struct smu_context *smu) int smu_v12_0_check_fw_version(struct smu_context *smu) { + struct amdgpu_device *adev = smu->adev; uint32_t if_version = 0xff, smu_version = 0xff; uint16_t smu_major; uint8_t smu_minor, smu_debug; @@ -83,6 +84,8 @@ int smu_v12_0_check_fw_version(struct smu_context *smu) smu_major = (smu_version >> 16) & 0xffff; smu_minor = (smu_version >> 8) & 0xff; smu_debug = (smu_version >> 0) & 0xff; + if (smu->is_apu) + adev->pm.fw_version = smu_version; /* * 1. if_version mismatch is not critical as our fw is designed diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c index dc28f22aeb38..f8260769061c 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c @@ -655,7 +655,7 @@ int smu_cmn_update_table(struct smu_context *smu, return ret; if (!drv2smu) { - amdgpu_asic_flush_hdp(adev, NULL); + amdgpu_asic_invalidate_hdp(adev, NULL); memcpy(table_data, table->cpu_addr, table_size); } diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h b/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h index f7be2d1a0ff2..68d9464ababc 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h @@ -90,6 +90,7 @@ #define smu_get_fan_parameters(smu) smu_ppt_funcs(get_fan_parameters, 0, smu) #define smu_post_init(smu) smu_ppt_funcs(post_init, 0, smu) #define smu_gpo_control(smu, enablement) smu_ppt_funcs(gpo_control, 0, smu, enablement) +#define smu_set_fine_grain_gfx_freq_parameters(smu) smu_ppt_funcs(set_fine_grain_gfx_freq_parameters, 0, smu) #endif #endif |