0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024 #include "smumgr.h"
0025 #include "vega12_inc.h"
0026 #include "soc15_common.h"
0027 #include "smu9_smumgr.h"
0028 #include "vega12_smumgr.h"
0029 #include "vega12_ppsmc.h"
0030 #include "vega12/smu9_driver_if.h"
0031 #include "ppatomctrl.h"
0032 #include "pp_debug.h"
0033
0034
0035
0036
0037
0038
0039
0040 static int vega12_copy_table_from_smc(struct pp_hwmgr *hwmgr,
0041 uint8_t *table, int16_t table_id)
0042 {
0043 struct vega12_smumgr *priv =
0044 (struct vega12_smumgr *)(hwmgr->smu_backend);
0045 struct amdgpu_device *adev = hwmgr->adev;
0046
0047 PP_ASSERT_WITH_CODE(table_id < TABLE_COUNT,
0048 "Invalid SMU Table ID!", return -EINVAL);
0049 PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0,
0050 "Invalid SMU Table version!", return -EINVAL);
0051 PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0,
0052 "Invalid SMU Table Length!", return -EINVAL);
0053 PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr,
0054 PPSMC_MSG_SetDriverDramAddrHigh,
0055 upper_32_bits(priv->smu_tables.entry[table_id].mc_addr),
0056 NULL) == 0,
0057 "[CopyTableFromSMC] Attempt to Set Dram Addr High Failed!", return -EINVAL);
0058 PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr,
0059 PPSMC_MSG_SetDriverDramAddrLow,
0060 lower_32_bits(priv->smu_tables.entry[table_id].mc_addr),
0061 NULL) == 0,
0062 "[CopyTableFromSMC] Attempt to Set Dram Addr Low Failed!",
0063 return -EINVAL);
0064 PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr,
0065 PPSMC_MSG_TransferTableSmu2Dram,
0066 table_id,
0067 NULL) == 0,
0068 "[CopyTableFromSMC] Attempt to Transfer Table From SMU Failed!",
0069 return -EINVAL);
0070
0071 amdgpu_asic_invalidate_hdp(adev, NULL);
0072
0073 memcpy(table, priv->smu_tables.entry[table_id].table,
0074 priv->smu_tables.entry[table_id].size);
0075
0076 return 0;
0077 }
0078
0079
0080
0081
0082
0083
0084 static int vega12_copy_table_to_smc(struct pp_hwmgr *hwmgr,
0085 uint8_t *table, int16_t table_id)
0086 {
0087 struct vega12_smumgr *priv =
0088 (struct vega12_smumgr *)(hwmgr->smu_backend);
0089 struct amdgpu_device *adev = hwmgr->adev;
0090
0091 PP_ASSERT_WITH_CODE(table_id < TABLE_COUNT,
0092 "Invalid SMU Table ID!", return -EINVAL);
0093 PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0,
0094 "Invalid SMU Table version!", return -EINVAL);
0095 PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0,
0096 "Invalid SMU Table Length!", return -EINVAL);
0097
0098 memcpy(priv->smu_tables.entry[table_id].table, table,
0099 priv->smu_tables.entry[table_id].size);
0100
0101 amdgpu_asic_flush_hdp(adev, NULL);
0102
0103 PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr,
0104 PPSMC_MSG_SetDriverDramAddrHigh,
0105 upper_32_bits(priv->smu_tables.entry[table_id].mc_addr),
0106 NULL) == 0,
0107 "[CopyTableToSMC] Attempt to Set Dram Addr High Failed!",
0108 return -EINVAL;);
0109 PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr,
0110 PPSMC_MSG_SetDriverDramAddrLow,
0111 lower_32_bits(priv->smu_tables.entry[table_id].mc_addr),
0112 NULL) == 0,
0113 "[CopyTableToSMC] Attempt to Set Dram Addr Low Failed!",
0114 return -EINVAL);
0115 PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr,
0116 PPSMC_MSG_TransferTableDram2Smu,
0117 table_id,
0118 NULL) == 0,
0119 "[CopyTableToSMC] Attempt to Transfer Table To SMU Failed!",
0120 return -EINVAL);
0121
0122 return 0;
0123 }
0124
0125 int vega12_enable_smc_features(struct pp_hwmgr *hwmgr,
0126 bool enable, uint64_t feature_mask)
0127 {
0128 uint32_t smu_features_low, smu_features_high;
0129
0130 smu_features_low = (uint32_t)((feature_mask & SMU_FEATURES_LOW_MASK) >> SMU_FEATURES_LOW_SHIFT);
0131 smu_features_high = (uint32_t)((feature_mask & SMU_FEATURES_HIGH_MASK) >> SMU_FEATURES_HIGH_SHIFT);
0132
0133 if (enable) {
0134 PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr,
0135 PPSMC_MSG_EnableSmuFeaturesLow, smu_features_low, NULL) == 0,
0136 "[EnableDisableSMCFeatures] Attempt to enable SMU features Low failed!",
0137 return -EINVAL);
0138 PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr,
0139 PPSMC_MSG_EnableSmuFeaturesHigh, smu_features_high, NULL) == 0,
0140 "[EnableDisableSMCFeatures] Attempt to enable SMU features High failed!",
0141 return -EINVAL);
0142 } else {
0143 PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr,
0144 PPSMC_MSG_DisableSmuFeaturesLow, smu_features_low, NULL) == 0,
0145 "[EnableDisableSMCFeatures] Attempt to disable SMU features Low failed!",
0146 return -EINVAL);
0147 PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr,
0148 PPSMC_MSG_DisableSmuFeaturesHigh, smu_features_high, NULL) == 0,
0149 "[EnableDisableSMCFeatures] Attempt to disable SMU features High failed!",
0150 return -EINVAL);
0151 }
0152
0153 return 0;
0154 }
0155
0156 int vega12_get_enabled_smc_features(struct pp_hwmgr *hwmgr,
0157 uint64_t *features_enabled)
0158 {
0159 uint32_t smc_features_low, smc_features_high;
0160
0161 if (features_enabled == NULL)
0162 return -EINVAL;
0163
0164 PP_ASSERT_WITH_CODE(smum_send_msg_to_smc(hwmgr,
0165 PPSMC_MSG_GetEnabledSmuFeaturesLow,
0166 &smc_features_low) == 0,
0167 "[GetEnabledSMCFeatures] Attempt to get SMU features Low failed!",
0168 return -EINVAL);
0169
0170 PP_ASSERT_WITH_CODE(smum_send_msg_to_smc(hwmgr,
0171 PPSMC_MSG_GetEnabledSmuFeaturesHigh,
0172 &smc_features_high) == 0,
0173 "[GetEnabledSMCFeatures] Attempt to get SMU features High failed!",
0174 return -EINVAL);
0175
0176 *features_enabled = ((((uint64_t)smc_features_low << SMU_FEATURES_LOW_SHIFT) & SMU_FEATURES_LOW_MASK) |
0177 (((uint64_t)smc_features_high << SMU_FEATURES_HIGH_SHIFT) & SMU_FEATURES_HIGH_MASK));
0178
0179 return 0;
0180 }
0181
0182 static bool vega12_is_dpm_running(struct pp_hwmgr *hwmgr)
0183 {
0184 uint64_t features_enabled = 0;
0185
0186 vega12_get_enabled_smc_features(hwmgr, &features_enabled);
0187
0188 if (features_enabled & SMC_DPM_FEATURES)
0189 return true;
0190 else
0191 return false;
0192 }
0193
0194 static int vega12_set_tools_address(struct pp_hwmgr *hwmgr)
0195 {
0196 struct vega12_smumgr *priv =
0197 (struct vega12_smumgr *)(hwmgr->smu_backend);
0198
0199 if (priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr) {
0200 if (!smum_send_msg_to_smc_with_parameter(hwmgr,
0201 PPSMC_MSG_SetToolsDramAddrHigh,
0202 upper_32_bits(priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr),
0203 NULL))
0204 smum_send_msg_to_smc_with_parameter(hwmgr,
0205 PPSMC_MSG_SetToolsDramAddrLow,
0206 lower_32_bits(priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr),
0207 NULL);
0208 }
0209 return 0;
0210 }
0211
0212 static int vega12_smu_init(struct pp_hwmgr *hwmgr)
0213 {
0214 struct vega12_smumgr *priv;
0215 unsigned long tools_size;
0216 struct cgs_firmware_info info = {0};
0217 int ret;
0218
0219 ret = cgs_get_firmware_info(hwmgr->device, CGS_UCODE_ID_SMU,
0220 &info);
0221 if (ret || !info.kptr)
0222 return -EINVAL;
0223
0224 priv = kzalloc(sizeof(struct vega12_smumgr), GFP_KERNEL);
0225 if (!priv)
0226 return -ENOMEM;
0227
0228 hwmgr->smu_backend = priv;
0229
0230
0231 ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
0232 sizeof(PPTable_t),
0233 PAGE_SIZE,
0234 AMDGPU_GEM_DOMAIN_VRAM,
0235 &priv->smu_tables.entry[TABLE_PPTABLE].handle,
0236 &priv->smu_tables.entry[TABLE_PPTABLE].mc_addr,
0237 &priv->smu_tables.entry[TABLE_PPTABLE].table);
0238 if (ret)
0239 goto free_backend;
0240
0241 priv->smu_tables.entry[TABLE_PPTABLE].version = 0x01;
0242 priv->smu_tables.entry[TABLE_PPTABLE].size = sizeof(PPTable_t);
0243
0244
0245 ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
0246 sizeof(Watermarks_t),
0247 PAGE_SIZE,
0248 AMDGPU_GEM_DOMAIN_VRAM,
0249 &priv->smu_tables.entry[TABLE_WATERMARKS].handle,
0250 &priv->smu_tables.entry[TABLE_WATERMARKS].mc_addr,
0251 &priv->smu_tables.entry[TABLE_WATERMARKS].table);
0252
0253 if (ret)
0254 goto err0;
0255
0256 priv->smu_tables.entry[TABLE_WATERMARKS].version = 0x01;
0257 priv->smu_tables.entry[TABLE_WATERMARKS].size = sizeof(Watermarks_t);
0258
0259 tools_size = 0x19000;
0260 if (tools_size) {
0261 ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
0262 tools_size,
0263 PAGE_SIZE,
0264 AMDGPU_GEM_DOMAIN_VRAM,
0265 &priv->smu_tables.entry[TABLE_PMSTATUSLOG].handle,
0266 &priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr,
0267 &priv->smu_tables.entry[TABLE_PMSTATUSLOG].table);
0268 if (ret)
0269 goto err1;
0270
0271 priv->smu_tables.entry[TABLE_PMSTATUSLOG].version = 0x01;
0272 priv->smu_tables.entry[TABLE_PMSTATUSLOG].size = tools_size;
0273 }
0274
0275
0276 ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
0277 sizeof(AvfsFuseOverride_t),
0278 PAGE_SIZE,
0279 AMDGPU_GEM_DOMAIN_VRAM,
0280 &priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].handle,
0281 &priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].mc_addr,
0282 &priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].table);
0283
0284 if (ret)
0285 goto err2;
0286
0287 priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].version = 0x01;
0288 priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].size = sizeof(AvfsFuseOverride_t);
0289
0290
0291 ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
0292 sizeof(OverDriveTable_t),
0293 PAGE_SIZE,
0294 AMDGPU_GEM_DOMAIN_VRAM,
0295 &priv->smu_tables.entry[TABLE_OVERDRIVE].handle,
0296 &priv->smu_tables.entry[TABLE_OVERDRIVE].mc_addr,
0297 &priv->smu_tables.entry[TABLE_OVERDRIVE].table);
0298 if (ret)
0299 goto err3;
0300
0301 priv->smu_tables.entry[TABLE_OVERDRIVE].version = 0x01;
0302 priv->smu_tables.entry[TABLE_OVERDRIVE].size = sizeof(OverDriveTable_t);
0303
0304
0305 ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
0306 sizeof(SmuMetrics_t),
0307 PAGE_SIZE,
0308 AMDGPU_GEM_DOMAIN_VRAM,
0309 &priv->smu_tables.entry[TABLE_SMU_METRICS].handle,
0310 &priv->smu_tables.entry[TABLE_SMU_METRICS].mc_addr,
0311 &priv->smu_tables.entry[TABLE_SMU_METRICS].table);
0312 if (ret)
0313 goto err4;
0314
0315 priv->smu_tables.entry[TABLE_SMU_METRICS].version = 0x01;
0316 priv->smu_tables.entry[TABLE_SMU_METRICS].size = sizeof(SmuMetrics_t);
0317
0318 return 0;
0319
0320 err4:
0321 amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_OVERDRIVE].handle,
0322 &priv->smu_tables.entry[TABLE_OVERDRIVE].mc_addr,
0323 &priv->smu_tables.entry[TABLE_OVERDRIVE].table);
0324 err3:
0325 amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].handle,
0326 &priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].mc_addr,
0327 &priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].table);
0328 err2:
0329 if (priv->smu_tables.entry[TABLE_PMSTATUSLOG].table)
0330 amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_PMSTATUSLOG].handle,
0331 &priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr,
0332 &priv->smu_tables.entry[TABLE_PMSTATUSLOG].table);
0333 err1:
0334 amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_WATERMARKS].handle,
0335 &priv->smu_tables.entry[TABLE_WATERMARKS].mc_addr,
0336 &priv->smu_tables.entry[TABLE_WATERMARKS].table);
0337 err0:
0338 amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_PPTABLE].handle,
0339 &priv->smu_tables.entry[TABLE_PPTABLE].mc_addr,
0340 &priv->smu_tables.entry[TABLE_PPTABLE].table);
0341 free_backend:
0342 kfree(hwmgr->smu_backend);
0343
0344 return -EINVAL;
0345 }
0346
0347 static int vega12_smu_fini(struct pp_hwmgr *hwmgr)
0348 {
0349 struct vega12_smumgr *priv =
0350 (struct vega12_smumgr *)(hwmgr->smu_backend);
0351
0352 if (priv) {
0353 amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_PPTABLE].handle,
0354 &priv->smu_tables.entry[TABLE_PPTABLE].mc_addr,
0355 &priv->smu_tables.entry[TABLE_PPTABLE].table);
0356 amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_WATERMARKS].handle,
0357 &priv->smu_tables.entry[TABLE_WATERMARKS].mc_addr,
0358 &priv->smu_tables.entry[TABLE_WATERMARKS].table);
0359 if (priv->smu_tables.entry[TABLE_PMSTATUSLOG].table)
0360 amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_PMSTATUSLOG].handle,
0361 &priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr,
0362 &priv->smu_tables.entry[TABLE_PMSTATUSLOG].table);
0363 amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].handle,
0364 &priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].mc_addr,
0365 &priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].table);
0366 amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_OVERDRIVE].handle,
0367 &priv->smu_tables.entry[TABLE_OVERDRIVE].mc_addr,
0368 &priv->smu_tables.entry[TABLE_OVERDRIVE].table);
0369 amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_SMU_METRICS].handle,
0370 &priv->smu_tables.entry[TABLE_SMU_METRICS].mc_addr,
0371 &priv->smu_tables.entry[TABLE_SMU_METRICS].table);
0372 kfree(hwmgr->smu_backend);
0373 hwmgr->smu_backend = NULL;
0374 }
0375 return 0;
0376 }
0377
0378 static int vega12_start_smu(struct pp_hwmgr *hwmgr)
0379 {
0380 PP_ASSERT_WITH_CODE(smu9_is_smc_ram_running(hwmgr),
0381 "SMC is not running!",
0382 return -EINVAL);
0383
0384 vega12_set_tools_address(hwmgr);
0385
0386 return 0;
0387 }
0388
0389 static int vega12_smc_table_manager(struct pp_hwmgr *hwmgr, uint8_t *table,
0390 uint16_t table_id, bool rw)
0391 {
0392 int ret;
0393
0394 if (rw)
0395 ret = vega12_copy_table_from_smc(hwmgr, table, table_id);
0396 else
0397 ret = vega12_copy_table_to_smc(hwmgr, table, table_id);
0398
0399 return ret;
0400 }
0401
0402 const struct pp_smumgr_func vega12_smu_funcs = {
0403 .name = "vega12_smu",
0404 .smu_init = &vega12_smu_init,
0405 .smu_fini = &vega12_smu_fini,
0406 .start_smu = &vega12_start_smu,
0407 .request_smu_load_specific_fw = NULL,
0408 .send_msg_to_smc = &smu9_send_msg_to_smc,
0409 .send_msg_to_smc_with_parameter = &smu9_send_msg_to_smc_with_parameter,
0410 .download_pptable_settings = NULL,
0411 .upload_pptable_settings = NULL,
0412 .is_dpm_running = vega12_is_dpm_running,
0413 .get_argument = smu9_get_argument,
0414 .smc_table_manager = vega12_smc_table_manager,
0415 };