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 <linux/pci.h>
0025
0026 #include "smumgr.h"
0027 #include "vega10_inc.h"
0028 #include "soc15_common.h"
0029 #include "vega10_smumgr.h"
0030 #include "vega10_hwmgr.h"
0031 #include "vega10_ppsmc.h"
0032 #include "smu9_driver_if.h"
0033 #include "smu9_smumgr.h"
0034 #include "ppatomctrl.h"
0035 #include "pp_debug.h"
0036
0037
0038 static int vega10_copy_table_from_smc(struct pp_hwmgr *hwmgr,
0039 uint8_t *table, int16_t table_id)
0040 {
0041 struct vega10_smumgr *priv = hwmgr->smu_backend;
0042 struct amdgpu_device *adev = hwmgr->adev;
0043
0044 PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE,
0045 "Invalid SMU Table ID!", return -EINVAL);
0046 PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0,
0047 "Invalid SMU Table version!", return -EINVAL);
0048 PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0,
0049 "Invalid SMU Table Length!", return -EINVAL);
0050 smum_send_msg_to_smc_with_parameter(hwmgr,
0051 PPSMC_MSG_SetDriverDramAddrHigh,
0052 upper_32_bits(priv->smu_tables.entry[table_id].mc_addr),
0053 NULL);
0054 smum_send_msg_to_smc_with_parameter(hwmgr,
0055 PPSMC_MSG_SetDriverDramAddrLow,
0056 lower_32_bits(priv->smu_tables.entry[table_id].mc_addr),
0057 NULL);
0058 smum_send_msg_to_smc_with_parameter(hwmgr,
0059 PPSMC_MSG_TransferTableSmu2Dram,
0060 priv->smu_tables.entry[table_id].table_id,
0061 NULL);
0062
0063 amdgpu_asic_invalidate_hdp(adev, NULL);
0064
0065 memcpy(table, priv->smu_tables.entry[table_id].table,
0066 priv->smu_tables.entry[table_id].size);
0067
0068 return 0;
0069 }
0070
0071 static int vega10_copy_table_to_smc(struct pp_hwmgr *hwmgr,
0072 uint8_t *table, int16_t table_id)
0073 {
0074 struct vega10_smumgr *priv = hwmgr->smu_backend;
0075 struct amdgpu_device *adev = hwmgr->adev;
0076
0077
0078
0079
0080 if (!hwmgr->not_vf)
0081 return 0;
0082
0083 PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE,
0084 "Invalid SMU Table ID!", return -EINVAL);
0085 PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0,
0086 "Invalid SMU Table version!", return -EINVAL);
0087 PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0,
0088 "Invalid SMU Table Length!", return -EINVAL);
0089
0090 memcpy(priv->smu_tables.entry[table_id].table, table,
0091 priv->smu_tables.entry[table_id].size);
0092
0093 amdgpu_asic_flush_hdp(adev, NULL);
0094
0095 smum_send_msg_to_smc_with_parameter(hwmgr,
0096 PPSMC_MSG_SetDriverDramAddrHigh,
0097 upper_32_bits(priv->smu_tables.entry[table_id].mc_addr),
0098 NULL);
0099 smum_send_msg_to_smc_with_parameter(hwmgr,
0100 PPSMC_MSG_SetDriverDramAddrLow,
0101 lower_32_bits(priv->smu_tables.entry[table_id].mc_addr),
0102 NULL);
0103 smum_send_msg_to_smc_with_parameter(hwmgr,
0104 PPSMC_MSG_TransferTableDram2Smu,
0105 priv->smu_tables.entry[table_id].table_id,
0106 NULL);
0107
0108 return 0;
0109 }
0110
0111 int vega10_enable_smc_features(struct pp_hwmgr *hwmgr,
0112 bool enable, uint32_t feature_mask)
0113 {
0114 int msg = enable ? PPSMC_MSG_EnableSmuFeatures :
0115 PPSMC_MSG_DisableSmuFeatures;
0116
0117
0118
0119
0120
0121
0122 if (!hwmgr->not_vf)
0123 return 0;
0124
0125 return smum_send_msg_to_smc_with_parameter(hwmgr,
0126 msg, feature_mask, NULL);
0127 }
0128
0129 int vega10_get_enabled_smc_features(struct pp_hwmgr *hwmgr,
0130 uint64_t *features_enabled)
0131 {
0132 uint32_t enabled_features;
0133
0134 if (features_enabled == NULL)
0135 return -EINVAL;
0136
0137 smum_send_msg_to_smc(hwmgr,
0138 PPSMC_MSG_GetEnabledSmuFeatures,
0139 &enabled_features);
0140 *features_enabled = enabled_features;
0141
0142 return 0;
0143 }
0144
0145 static bool vega10_is_dpm_running(struct pp_hwmgr *hwmgr)
0146 {
0147 uint64_t features_enabled = 0;
0148
0149 vega10_get_enabled_smc_features(hwmgr, &features_enabled);
0150
0151 if (features_enabled & SMC_DPM_FEATURES)
0152 return true;
0153 else
0154 return false;
0155 }
0156
0157 static int vega10_set_tools_address(struct pp_hwmgr *hwmgr)
0158 {
0159 struct vega10_smumgr *priv = hwmgr->smu_backend;
0160
0161 if (priv->smu_tables.entry[TOOLSTABLE].mc_addr) {
0162 smum_send_msg_to_smc_with_parameter(hwmgr,
0163 PPSMC_MSG_SetToolsDramAddrHigh,
0164 upper_32_bits(priv->smu_tables.entry[TOOLSTABLE].mc_addr),
0165 NULL);
0166 smum_send_msg_to_smc_with_parameter(hwmgr,
0167 PPSMC_MSG_SetToolsDramAddrLow,
0168 lower_32_bits(priv->smu_tables.entry[TOOLSTABLE].mc_addr),
0169 NULL);
0170 }
0171 return 0;
0172 }
0173
0174 static int vega10_verify_smc_interface(struct pp_hwmgr *hwmgr)
0175 {
0176 uint32_t smc_driver_if_version;
0177 struct amdgpu_device *adev = hwmgr->adev;
0178 uint32_t dev_id;
0179 uint32_t rev_id;
0180
0181 PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc(hwmgr,
0182 PPSMC_MSG_GetDriverIfVersion,
0183 &smc_driver_if_version),
0184 "Attempt to get SMC IF Version Number Failed!",
0185 return -EINVAL);
0186
0187 dev_id = adev->pdev->device;
0188 rev_id = adev->pdev->revision;
0189
0190 if (!((dev_id == 0x687f) &&
0191 ((rev_id == 0xc0) ||
0192 (rev_id == 0xc1) ||
0193 (rev_id == 0xc3)))) {
0194 if (smc_driver_if_version != SMU9_DRIVER_IF_VERSION) {
0195 pr_err("Your firmware(0x%x) doesn't match SMU9_DRIVER_IF_VERSION(0x%x). Please update your firmware!\n",
0196 smc_driver_if_version, SMU9_DRIVER_IF_VERSION);
0197 return -EINVAL;
0198 }
0199 }
0200
0201 return 0;
0202 }
0203
0204 static int vega10_smu_init(struct pp_hwmgr *hwmgr)
0205 {
0206 struct vega10_smumgr *priv;
0207 unsigned long tools_size;
0208 int ret;
0209 struct cgs_firmware_info info = {0};
0210
0211 ret = cgs_get_firmware_info(hwmgr->device,
0212 CGS_UCODE_ID_SMU,
0213 &info);
0214 if (ret || !info.kptr)
0215 return -EINVAL;
0216
0217 priv = kzalloc(sizeof(struct vega10_smumgr), GFP_KERNEL);
0218
0219 if (!priv)
0220 return -ENOMEM;
0221
0222 hwmgr->smu_backend = priv;
0223
0224
0225 ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
0226 sizeof(PPTable_t),
0227 PAGE_SIZE,
0228 AMDGPU_GEM_DOMAIN_VRAM,
0229 &priv->smu_tables.entry[PPTABLE].handle,
0230 &priv->smu_tables.entry[PPTABLE].mc_addr,
0231 &priv->smu_tables.entry[PPTABLE].table);
0232 if (ret)
0233 goto free_backend;
0234
0235 priv->smu_tables.entry[PPTABLE].version = 0x01;
0236 priv->smu_tables.entry[PPTABLE].size = sizeof(PPTable_t);
0237 priv->smu_tables.entry[PPTABLE].table_id = TABLE_PPTABLE;
0238
0239
0240 ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
0241 sizeof(Watermarks_t),
0242 PAGE_SIZE,
0243 AMDGPU_GEM_DOMAIN_VRAM,
0244 &priv->smu_tables.entry[WMTABLE].handle,
0245 &priv->smu_tables.entry[WMTABLE].mc_addr,
0246 &priv->smu_tables.entry[WMTABLE].table);
0247
0248 if (ret)
0249 goto err0;
0250
0251 priv->smu_tables.entry[WMTABLE].version = 0x01;
0252 priv->smu_tables.entry[WMTABLE].size = sizeof(Watermarks_t);
0253 priv->smu_tables.entry[WMTABLE].table_id = TABLE_WATERMARKS;
0254
0255
0256 ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
0257 sizeof(AvfsTable_t),
0258 PAGE_SIZE,
0259 AMDGPU_GEM_DOMAIN_VRAM,
0260 &priv->smu_tables.entry[AVFSTABLE].handle,
0261 &priv->smu_tables.entry[AVFSTABLE].mc_addr,
0262 &priv->smu_tables.entry[AVFSTABLE].table);
0263
0264 if (ret)
0265 goto err1;
0266
0267 priv->smu_tables.entry[AVFSTABLE].version = 0x01;
0268 priv->smu_tables.entry[AVFSTABLE].size = sizeof(AvfsTable_t);
0269 priv->smu_tables.entry[AVFSTABLE].table_id = TABLE_AVFS;
0270
0271 tools_size = 0x19000;
0272 if (tools_size) {
0273 ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
0274 tools_size,
0275 PAGE_SIZE,
0276 AMDGPU_GEM_DOMAIN_VRAM,
0277 &priv->smu_tables.entry[TOOLSTABLE].handle,
0278 &priv->smu_tables.entry[TOOLSTABLE].mc_addr,
0279 &priv->smu_tables.entry[TOOLSTABLE].table);
0280 if (ret)
0281 goto err2;
0282 priv->smu_tables.entry[TOOLSTABLE].version = 0x01;
0283 priv->smu_tables.entry[TOOLSTABLE].size = tools_size;
0284 priv->smu_tables.entry[TOOLSTABLE].table_id = TABLE_PMSTATUSLOG;
0285 }
0286
0287
0288 ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
0289 sizeof(AvfsFuseOverride_t),
0290 PAGE_SIZE,
0291 AMDGPU_GEM_DOMAIN_VRAM,
0292 &priv->smu_tables.entry[AVFSFUSETABLE].handle,
0293 &priv->smu_tables.entry[AVFSFUSETABLE].mc_addr,
0294 &priv->smu_tables.entry[AVFSFUSETABLE].table);
0295 if (ret)
0296 goto err3;
0297
0298 priv->smu_tables.entry[AVFSFUSETABLE].version = 0x01;
0299 priv->smu_tables.entry[AVFSFUSETABLE].size = sizeof(AvfsFuseOverride_t);
0300 priv->smu_tables.entry[AVFSFUSETABLE].table_id = TABLE_AVFS_FUSE_OVERRIDE;
0301
0302
0303 return 0;
0304
0305 err3:
0306 if (priv->smu_tables.entry[TOOLSTABLE].table)
0307 amdgpu_bo_free_kernel(&priv->smu_tables.entry[TOOLSTABLE].handle,
0308 &priv->smu_tables.entry[TOOLSTABLE].mc_addr,
0309 &priv->smu_tables.entry[TOOLSTABLE].table);
0310 err2:
0311 amdgpu_bo_free_kernel(&priv->smu_tables.entry[AVFSTABLE].handle,
0312 &priv->smu_tables.entry[AVFSTABLE].mc_addr,
0313 &priv->smu_tables.entry[AVFSTABLE].table);
0314 err1:
0315 amdgpu_bo_free_kernel(&priv->smu_tables.entry[WMTABLE].handle,
0316 &priv->smu_tables.entry[WMTABLE].mc_addr,
0317 &priv->smu_tables.entry[WMTABLE].table);
0318 err0:
0319 amdgpu_bo_free_kernel(&priv->smu_tables.entry[PPTABLE].handle,
0320 &priv->smu_tables.entry[PPTABLE].mc_addr,
0321 &priv->smu_tables.entry[PPTABLE].table);
0322 free_backend:
0323 kfree(hwmgr->smu_backend);
0324
0325 return -EINVAL;
0326 }
0327
0328 static int vega10_smu_fini(struct pp_hwmgr *hwmgr)
0329 {
0330 struct vega10_smumgr *priv = hwmgr->smu_backend;
0331
0332 if (priv) {
0333 amdgpu_bo_free_kernel(&priv->smu_tables.entry[PPTABLE].handle,
0334 &priv->smu_tables.entry[PPTABLE].mc_addr,
0335 &priv->smu_tables.entry[PPTABLE].table);
0336 amdgpu_bo_free_kernel(&priv->smu_tables.entry[WMTABLE].handle,
0337 &priv->smu_tables.entry[WMTABLE].mc_addr,
0338 &priv->smu_tables.entry[WMTABLE].table);
0339 amdgpu_bo_free_kernel(&priv->smu_tables.entry[AVFSTABLE].handle,
0340 &priv->smu_tables.entry[AVFSTABLE].mc_addr,
0341 &priv->smu_tables.entry[AVFSTABLE].table);
0342 if (priv->smu_tables.entry[TOOLSTABLE].table)
0343 amdgpu_bo_free_kernel(&priv->smu_tables.entry[TOOLSTABLE].handle,
0344 &priv->smu_tables.entry[TOOLSTABLE].mc_addr,
0345 &priv->smu_tables.entry[TOOLSTABLE].table);
0346 amdgpu_bo_free_kernel(&priv->smu_tables.entry[AVFSFUSETABLE].handle,
0347 &priv->smu_tables.entry[AVFSFUSETABLE].mc_addr,
0348 &priv->smu_tables.entry[AVFSFUSETABLE].table);
0349 kfree(hwmgr->smu_backend);
0350 hwmgr->smu_backend = NULL;
0351 }
0352 return 0;
0353 }
0354
0355 static int vega10_start_smu(struct pp_hwmgr *hwmgr)
0356 {
0357 if (!smu9_is_smc_ram_running(hwmgr))
0358 return -EINVAL;
0359
0360 PP_ASSERT_WITH_CODE(!vega10_verify_smc_interface(hwmgr),
0361 "Failed to verify SMC interface!",
0362 return -EINVAL);
0363
0364 vega10_set_tools_address(hwmgr);
0365
0366 return 0;
0367 }
0368
0369 static int vega10_smc_table_manager(struct pp_hwmgr *hwmgr, uint8_t *table,
0370 uint16_t table_id, bool rw)
0371 {
0372 int ret;
0373
0374 if (rw)
0375 ret = vega10_copy_table_from_smc(hwmgr, table, table_id);
0376 else
0377 ret = vega10_copy_table_to_smc(hwmgr, table, table_id);
0378
0379 return ret;
0380 }
0381
0382 const struct pp_smumgr_func vega10_smu_funcs = {
0383 .name = "vega10_smu",
0384 .smu_init = &vega10_smu_init,
0385 .smu_fini = &vega10_smu_fini,
0386 .start_smu = &vega10_start_smu,
0387 .request_smu_load_specific_fw = NULL,
0388 .send_msg_to_smc = &smu9_send_msg_to_smc,
0389 .send_msg_to_smc_with_parameter = &smu9_send_msg_to_smc_with_parameter,
0390 .download_pptable_settings = NULL,
0391 .upload_pptable_settings = NULL,
0392 .is_dpm_running = vega10_is_dpm_running,
0393 .get_argument = smu9_get_argument,
0394 .smc_table_manager = vega10_smc_table_manager,
0395 };