0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023 #define SWSMU_CODE_LAYER_L3
0024
0025 #include <linux/firmware.h>
0026 #include "amdgpu.h"
0027 #include "amdgpu_smu.h"
0028 #include "atomfirmware.h"
0029 #include "amdgpu_atomfirmware.h"
0030 #include "amdgpu_atombios.h"
0031 #include "smu_v12_0.h"
0032 #include "soc15_common.h"
0033 #include "atom.h"
0034 #include "smu_cmn.h"
0035
0036 #include "asic_reg/mp/mp_12_0_0_offset.h"
0037 #include "asic_reg/mp/mp_12_0_0_sh_mask.h"
0038 #include "asic_reg/smuio/smuio_12_0_0_offset.h"
0039 #include "asic_reg/smuio/smuio_12_0_0_sh_mask.h"
0040
0041
0042
0043
0044
0045
0046 #undef pr_err
0047 #undef pr_warn
0048 #undef pr_info
0049 #undef pr_debug
0050
0051
0052
0053
0054 #undef mmPWR_MISC_CNTL_STATUS
0055
0056 #define smnMP1_FIRMWARE_FLAGS 0x3010024
0057
0058 int smu_v12_0_check_fw_status(struct smu_context *smu)
0059 {
0060 struct amdgpu_device *adev = smu->adev;
0061 uint32_t mp1_fw_flags;
0062
0063 mp1_fw_flags = RREG32_PCIE(MP1_Public |
0064 (smnMP1_FIRMWARE_FLAGS & 0xffffffff));
0065
0066 if ((mp1_fw_flags & MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED_MASK) >>
0067 MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED__SHIFT)
0068 return 0;
0069
0070 return -EIO;
0071 }
0072
0073 int smu_v12_0_check_fw_version(struct smu_context *smu)
0074 {
0075 struct amdgpu_device *adev = smu->adev;
0076 uint32_t if_version = 0xff, smu_version = 0xff;
0077 uint8_t smu_program, smu_major, smu_minor, smu_debug;
0078 int ret = 0;
0079
0080 ret = smu_cmn_get_smc_version(smu, &if_version, &smu_version);
0081 if (ret)
0082 return ret;
0083
0084 smu_program = (smu_version >> 24) & 0xff;
0085 smu_major = (smu_version >> 16) & 0xff;
0086 smu_minor = (smu_version >> 8) & 0xff;
0087 smu_debug = (smu_version >> 0) & 0xff;
0088 if (smu->is_apu)
0089 adev->pm.fw_version = smu_version;
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099 if (if_version != smu->smc_driver_if_version) {
0100 dev_info(smu->adev->dev, "smu driver if version = 0x%08x, smu fw if version = 0x%08x, "
0101 "smu fw program = %d, smu fw version = 0x%08x (%d.%d.%d)\n",
0102 smu->smc_driver_if_version, if_version,
0103 smu_program, smu_version, smu_major, smu_minor, smu_debug);
0104 dev_warn(smu->adev->dev, "SMU driver if version not matched\n");
0105 }
0106
0107 return ret;
0108 }
0109
0110 int smu_v12_0_powergate_sdma(struct smu_context *smu, bool gate)
0111 {
0112 if (!smu->is_apu)
0113 return 0;
0114
0115 if (gate)
0116 return smu_cmn_send_smc_msg(smu, SMU_MSG_PowerDownSdma, NULL);
0117 else
0118 return smu_cmn_send_smc_msg(smu, SMU_MSG_PowerUpSdma, NULL);
0119 }
0120
0121 int smu_v12_0_set_gfx_cgpg(struct smu_context *smu, bool enable)
0122 {
0123
0124 if (!(smu->adev->pg_flags & AMD_PG_SUPPORT_GFX_PG) || smu->adev->in_s0ix)
0125 return 0;
0126
0127 return smu_cmn_send_smc_msg_with_param(smu,
0128 SMU_MSG_SetGfxCGPG,
0129 enable ? 1 : 0,
0130 NULL);
0131 }
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145 uint32_t smu_v12_0_get_gfxoff_status(struct smu_context *smu)
0146 {
0147 uint32_t reg;
0148 uint32_t gfxOff_Status = 0;
0149 struct amdgpu_device *adev = smu->adev;
0150
0151 reg = RREG32_SOC15(SMUIO, 0, mmSMUIO_GFX_MISC_CNTL);
0152 gfxOff_Status = (reg & SMUIO_GFX_MISC_CNTL__PWR_GFXOFF_STATUS_MASK)
0153 >> SMUIO_GFX_MISC_CNTL__PWR_GFXOFF_STATUS__SHIFT;
0154
0155 return gfxOff_Status;
0156 }
0157
0158 int smu_v12_0_gfx_off_control(struct smu_context *smu, bool enable)
0159 {
0160 int ret = 0, timeout = 500;
0161
0162 if (enable) {
0163 ret = smu_cmn_send_smc_msg(smu, SMU_MSG_AllowGfxOff, NULL);
0164
0165 } else {
0166 ret = smu_cmn_send_smc_msg(smu, SMU_MSG_DisallowGfxOff, NULL);
0167
0168
0169 while (!(smu_v12_0_get_gfxoff_status(smu) == 2)) {
0170 msleep(1);
0171 timeout--;
0172 if (timeout == 0) {
0173 DRM_ERROR("disable gfxoff timeout and failed!\n");
0174 break;
0175 }
0176 }
0177 }
0178
0179 return ret;
0180 }
0181
0182 int smu_v12_0_fini_smc_tables(struct smu_context *smu)
0183 {
0184 struct smu_table_context *smu_table = &smu->smu_table;
0185
0186 kfree(smu_table->clocks_table);
0187 smu_table->clocks_table = NULL;
0188
0189 kfree(smu_table->metrics_table);
0190 smu_table->metrics_table = NULL;
0191
0192 kfree(smu_table->watermarks_table);
0193 smu_table->watermarks_table = NULL;
0194
0195 kfree(smu_table->gpu_metrics_table);
0196 smu_table->gpu_metrics_table = NULL;
0197
0198 return 0;
0199 }
0200
0201 int smu_v12_0_set_default_dpm_tables(struct smu_context *smu)
0202 {
0203 struct smu_table_context *smu_table = &smu->smu_table;
0204
0205 return smu_cmn_update_table(smu, SMU_TABLE_DPMCLOCKS, 0, smu_table->clocks_table, false);
0206 }
0207
0208 int smu_v12_0_mode2_reset(struct smu_context *smu){
0209 return smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_GfxDeviceDriverReset, SMU_RESET_MODE_2, NULL);
0210 }
0211
0212 int smu_v12_0_set_soft_freq_limited_range(struct smu_context *smu, enum smu_clk_type clk_type,
0213 uint32_t min, uint32_t max)
0214 {
0215 int ret = 0;
0216
0217 if (!smu_cmn_clk_dpm_is_enabled(smu, clk_type))
0218 return 0;
0219
0220 switch (clk_type) {
0221 case SMU_GFXCLK:
0222 case SMU_SCLK:
0223 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinGfxClk, min, NULL);
0224 if (ret)
0225 return ret;
0226
0227 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk, max, NULL);
0228 if (ret)
0229 return ret;
0230 break;
0231 case SMU_FCLK:
0232 case SMU_MCLK:
0233 case SMU_UCLK:
0234 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinFclkByFreq, min, NULL);
0235 if (ret)
0236 return ret;
0237
0238 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxFclkByFreq, max, NULL);
0239 if (ret)
0240 return ret;
0241 break;
0242 case SMU_SOCCLK:
0243 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinSocclkByFreq, min, NULL);
0244 if (ret)
0245 return ret;
0246
0247 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxSocclkByFreq, max, NULL);
0248 if (ret)
0249 return ret;
0250 break;
0251 case SMU_VCLK:
0252 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinVcn, min, NULL);
0253 if (ret)
0254 return ret;
0255
0256 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxVcn, max, NULL);
0257 if (ret)
0258 return ret;
0259 break;
0260 default:
0261 return -EINVAL;
0262 }
0263
0264 return ret;
0265 }
0266
0267 int smu_v12_0_set_driver_table_location(struct smu_context *smu)
0268 {
0269 struct smu_table *driver_table = &smu->smu_table.driver_table;
0270 int ret = 0;
0271
0272 if (driver_table->mc_address) {
0273 ret = smu_cmn_send_smc_msg_with_param(smu,
0274 SMU_MSG_SetDriverDramAddrHigh,
0275 upper_32_bits(driver_table->mc_address),
0276 NULL);
0277 if (!ret)
0278 ret = smu_cmn_send_smc_msg_with_param(smu,
0279 SMU_MSG_SetDriverDramAddrLow,
0280 lower_32_bits(driver_table->mc_address),
0281 NULL);
0282 }
0283
0284 return ret;
0285 }
0286
0287 static int smu_v12_0_atom_get_smu_clockinfo(struct amdgpu_device *adev,
0288 uint8_t clk_id,
0289 uint8_t syspll_id,
0290 uint32_t *clk_freq)
0291 {
0292 struct atom_get_smu_clock_info_parameters_v3_1 input = {0};
0293 struct atom_get_smu_clock_info_output_parameters_v3_1 *output;
0294 int ret, index;
0295
0296 input.clk_id = clk_id;
0297 input.syspll_id = syspll_id;
0298 input.command = GET_SMU_CLOCK_INFO_V3_1_GET_CLOCK_FREQ;
0299 index = get_index_into_master_table(atom_master_list_of_command_functions_v2_1,
0300 getsmuclockinfo);
0301
0302 ret = amdgpu_atom_execute_table(adev->mode_info.atom_context, index,
0303 (uint32_t *)&input);
0304 if (ret)
0305 return -EINVAL;
0306
0307 output = (struct atom_get_smu_clock_info_output_parameters_v3_1 *)&input;
0308 *clk_freq = le32_to_cpu(output->atom_smu_outputclkfreq.smu_clock_freq_hz) / 10000;
0309
0310 return 0;
0311 }
0312
0313 int smu_v12_0_get_vbios_bootup_values(struct smu_context *smu)
0314 {
0315 int ret, index;
0316 uint16_t size;
0317 uint8_t frev, crev;
0318 struct atom_common_table_header *header;
0319 struct atom_firmware_info_v3_1 *v_3_1;
0320 struct atom_firmware_info_v3_3 *v_3_3;
0321
0322 index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
0323 firmwareinfo);
0324
0325 ret = amdgpu_atombios_get_data_table(smu->adev, index, &size, &frev, &crev,
0326 (uint8_t **)&header);
0327 if (ret)
0328 return ret;
0329
0330 if (header->format_revision != 3) {
0331 dev_err(smu->adev->dev, "unknown atom_firmware_info version! for smu12\n");
0332 return -EINVAL;
0333 }
0334
0335 switch (header->content_revision) {
0336 case 0:
0337 case 1:
0338 case 2:
0339 v_3_1 = (struct atom_firmware_info_v3_1 *)header;
0340 smu->smu_table.boot_values.revision = v_3_1->firmware_revision;
0341 smu->smu_table.boot_values.gfxclk = v_3_1->bootup_sclk_in10khz;
0342 smu->smu_table.boot_values.uclk = v_3_1->bootup_mclk_in10khz;
0343 smu->smu_table.boot_values.socclk = 0;
0344 smu->smu_table.boot_values.dcefclk = 0;
0345 smu->smu_table.boot_values.vddc = v_3_1->bootup_vddc_mv;
0346 smu->smu_table.boot_values.vddci = v_3_1->bootup_vddci_mv;
0347 smu->smu_table.boot_values.mvddc = v_3_1->bootup_mvddc_mv;
0348 smu->smu_table.boot_values.vdd_gfx = v_3_1->bootup_vddgfx_mv;
0349 smu->smu_table.boot_values.cooling_id = v_3_1->coolingsolution_id;
0350 smu->smu_table.boot_values.pp_table_id = 0;
0351 smu->smu_table.boot_values.firmware_caps = v_3_1->firmware_capability;
0352 break;
0353 case 3:
0354 case 4:
0355 default:
0356 v_3_3 = (struct atom_firmware_info_v3_3 *)header;
0357 smu->smu_table.boot_values.revision = v_3_3->firmware_revision;
0358 smu->smu_table.boot_values.gfxclk = v_3_3->bootup_sclk_in10khz;
0359 smu->smu_table.boot_values.uclk = v_3_3->bootup_mclk_in10khz;
0360 smu->smu_table.boot_values.socclk = 0;
0361 smu->smu_table.boot_values.dcefclk = 0;
0362 smu->smu_table.boot_values.vddc = v_3_3->bootup_vddc_mv;
0363 smu->smu_table.boot_values.vddci = v_3_3->bootup_vddci_mv;
0364 smu->smu_table.boot_values.mvddc = v_3_3->bootup_mvddc_mv;
0365 smu->smu_table.boot_values.vdd_gfx = v_3_3->bootup_vddgfx_mv;
0366 smu->smu_table.boot_values.cooling_id = v_3_3->coolingsolution_id;
0367 smu->smu_table.boot_values.pp_table_id = v_3_3->pplib_pptable_id;
0368 smu->smu_table.boot_values.firmware_caps = v_3_3->firmware_capability;
0369 }
0370
0371 smu->smu_table.boot_values.format_revision = header->format_revision;
0372 smu->smu_table.boot_values.content_revision = header->content_revision;
0373
0374 smu_v12_0_atom_get_smu_clockinfo(smu->adev,
0375 (uint8_t)SMU12_SYSPLL0_SOCCLK_ID,
0376 (uint8_t)SMU12_SYSPLL0_ID,
0377 &smu->smu_table.boot_values.socclk);
0378
0379 smu_v12_0_atom_get_smu_clockinfo(smu->adev,
0380 (uint8_t)SMU12_SYSPLL1_DCFCLK_ID,
0381 (uint8_t)SMU12_SYSPLL1_ID,
0382 &smu->smu_table.boot_values.dcefclk);
0383
0384 smu_v12_0_atom_get_smu_clockinfo(smu->adev,
0385 (uint8_t)SMU12_SYSPLL0_VCLK_ID,
0386 (uint8_t)SMU12_SYSPLL0_ID,
0387 &smu->smu_table.boot_values.vclk);
0388
0389 smu_v12_0_atom_get_smu_clockinfo(smu->adev,
0390 (uint8_t)SMU12_SYSPLL0_DCLK_ID,
0391 (uint8_t)SMU12_SYSPLL0_ID,
0392 &smu->smu_table.boot_values.dclk);
0393
0394 if ((smu->smu_table.boot_values.format_revision == 3) &&
0395 (smu->smu_table.boot_values.content_revision >= 2))
0396 smu_v12_0_atom_get_smu_clockinfo(smu->adev,
0397 (uint8_t)SMU12_SYSPLL3_0_FCLK_ID,
0398 (uint8_t)SMU12_SYSPLL3_0_ID,
0399 &smu->smu_table.boot_values.fclk);
0400
0401 smu_v12_0_atom_get_smu_clockinfo(smu->adev,
0402 (uint8_t)SMU12_SYSPLL0_LCLK_ID,
0403 (uint8_t)SMU12_SYSPLL0_ID,
0404 &smu->smu_table.boot_values.lclk);
0405
0406 return 0;
0407 }