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/delay.h>
0025 #include <linux/gfp.h>
0026 #include <linux/kernel.h>
0027 #include <linux/ktime.h>
0028 #include <linux/slab.h>
0029 #include <linux/types.h>
0030
0031 #include "cgs_common.h"
0032 #include "smu/smu_8_0_d.h"
0033 #include "smu/smu_8_0_sh_mask.h"
0034 #include "smu8.h"
0035 #include "smu8_fusion.h"
0036 #include "smu8_smumgr.h"
0037 #include "cz_ppsmc.h"
0038 #include "smu_ucode_xfer_cz.h"
0039 #include "gca/gfx_8_0_d.h"
0040 #include "gca/gfx_8_0_sh_mask.h"
0041 #include "smumgr.h"
0042
0043 #define SIZE_ALIGN_32(x) (((x) + 31) / 32 * 32)
0044
0045 static const enum smu8_scratch_entry firmware_list[] = {
0046 SMU8_SCRATCH_ENTRY_UCODE_ID_SDMA0,
0047 SMU8_SCRATCH_ENTRY_UCODE_ID_SDMA1,
0048 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_CE,
0049 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_PFP,
0050 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_ME,
0051 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1,
0052 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2,
0053 SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_G,
0054 };
0055
0056 static uint32_t smu8_get_argument(struct pp_hwmgr *hwmgr)
0057 {
0058 if (hwmgr == NULL || hwmgr->device == NULL)
0059 return 0;
0060
0061 return cgs_read_register(hwmgr->device,
0062 mmSMU_MP1_SRBM2P_ARG_0);
0063 }
0064
0065
0066 static int smu8_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr,
0067 uint16_t msg, uint32_t parameter)
0068 {
0069 int result = 0;
0070 ktime_t t_start;
0071 s64 elapsed_us;
0072
0073 if (hwmgr == NULL || hwmgr->device == NULL)
0074 return -EINVAL;
0075
0076 result = PHM_WAIT_FIELD_UNEQUAL(hwmgr,
0077 SMU_MP1_SRBM2P_RESP_0, CONTENT, 0);
0078 if (result != 0) {
0079
0080 uint32_t val = cgs_read_register(hwmgr->device,
0081 mmSMU_MP1_SRBM2P_MSG_0);
0082 pr_err("%s(0x%04x) aborted; SMU still servicing msg (0x%04x)\n",
0083 __func__, msg, val);
0084 return result;
0085 }
0086 t_start = ktime_get();
0087
0088 cgs_write_register(hwmgr->device, mmSMU_MP1_SRBM2P_ARG_0, parameter);
0089
0090 cgs_write_register(hwmgr->device, mmSMU_MP1_SRBM2P_RESP_0, 0);
0091 cgs_write_register(hwmgr->device, mmSMU_MP1_SRBM2P_MSG_0, msg);
0092
0093 result = PHM_WAIT_FIELD_UNEQUAL(hwmgr,
0094 SMU_MP1_SRBM2P_RESP_0, CONTENT, 0);
0095
0096 elapsed_us = ktime_us_delta(ktime_get(), t_start);
0097
0098 WARN(result, "%s(0x%04x, %#x) timed out after %lld us\n",
0099 __func__, msg, parameter, elapsed_us);
0100
0101 return result;
0102 }
0103
0104 static int smu8_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg)
0105 {
0106 return smu8_send_msg_to_smc_with_parameter(hwmgr, msg, 0);
0107 }
0108
0109 static int smu8_set_smc_sram_address(struct pp_hwmgr *hwmgr,
0110 uint32_t smc_address, uint32_t limit)
0111 {
0112 if (hwmgr == NULL || hwmgr->device == NULL)
0113 return -EINVAL;
0114
0115 if (0 != (3 & smc_address)) {
0116 pr_err("SMC address must be 4 byte aligned\n");
0117 return -EINVAL;
0118 }
0119
0120 if (limit <= (smc_address + 3)) {
0121 pr_err("SMC address beyond the SMC RAM area\n");
0122 return -EINVAL;
0123 }
0124
0125 cgs_write_register(hwmgr->device, mmMP0PUB_IND_INDEX_0,
0126 SMN_MP1_SRAM_START_ADDR + smc_address);
0127
0128 return 0;
0129 }
0130
0131 static int smu8_write_smc_sram_dword(struct pp_hwmgr *hwmgr,
0132 uint32_t smc_address, uint32_t value, uint32_t limit)
0133 {
0134 int result;
0135
0136 if (hwmgr == NULL || hwmgr->device == NULL)
0137 return -EINVAL;
0138
0139 result = smu8_set_smc_sram_address(hwmgr, smc_address, limit);
0140 if (!result)
0141 cgs_write_register(hwmgr->device, mmMP0PUB_IND_DATA_0, value);
0142
0143 return result;
0144 }
0145
0146 static int smu8_check_fw_load_finish(struct pp_hwmgr *hwmgr,
0147 uint32_t firmware)
0148 {
0149 int i;
0150 uint32_t index = SMN_MP1_SRAM_START_ADDR +
0151 SMU8_FIRMWARE_HEADER_LOCATION +
0152 offsetof(struct SMU8_Firmware_Header, UcodeLoadStatus);
0153
0154 if (hwmgr == NULL || hwmgr->device == NULL)
0155 return -EINVAL;
0156
0157 cgs_write_register(hwmgr->device, mmMP0PUB_IND_INDEX, index);
0158
0159 for (i = 0; i < hwmgr->usec_timeout; i++) {
0160 if (firmware ==
0161 (cgs_read_register(hwmgr->device, mmMP0PUB_IND_DATA) & firmware))
0162 break;
0163 udelay(1);
0164 }
0165
0166 if (i >= hwmgr->usec_timeout) {
0167 pr_err("SMU check loaded firmware failed.\n");
0168 return -EINVAL;
0169 }
0170
0171 return 0;
0172 }
0173
0174 static int smu8_load_mec_firmware(struct pp_hwmgr *hwmgr)
0175 {
0176 uint32_t reg_data;
0177 uint32_t tmp;
0178 int ret = 0;
0179 struct cgs_firmware_info info = {0};
0180
0181 if (hwmgr == NULL || hwmgr->device == NULL)
0182 return -EINVAL;
0183
0184 ret = cgs_get_firmware_info(hwmgr->device,
0185 CGS_UCODE_ID_CP_MEC, &info);
0186
0187 if (ret)
0188 return -EINVAL;
0189
0190
0191 tmp = cgs_read_register(hwmgr->device,
0192 mmCP_MEC_CNTL);
0193 tmp = PHM_SET_FIELD(tmp, CP_MEC_CNTL, MEC_ME1_HALT, 1);
0194 tmp = PHM_SET_FIELD(tmp, CP_MEC_CNTL, MEC_ME2_HALT, 1);
0195 cgs_write_register(hwmgr->device, mmCP_MEC_CNTL, tmp);
0196
0197 tmp = cgs_read_register(hwmgr->device,
0198 mmCP_CPC_IC_BASE_CNTL);
0199
0200 tmp = PHM_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, VMID, 0);
0201 tmp = PHM_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, ATC, 0);
0202 tmp = PHM_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, CACHE_POLICY, 0);
0203 tmp = PHM_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, MTYPE, 1);
0204 cgs_write_register(hwmgr->device, mmCP_CPC_IC_BASE_CNTL, tmp);
0205
0206 reg_data = lower_32_bits(info.mc_addr) &
0207 PHM_FIELD_MASK(CP_CPC_IC_BASE_LO, IC_BASE_LO);
0208 cgs_write_register(hwmgr->device, mmCP_CPC_IC_BASE_LO, reg_data);
0209
0210 reg_data = upper_32_bits(info.mc_addr) &
0211 PHM_FIELD_MASK(CP_CPC_IC_BASE_HI, IC_BASE_HI);
0212 cgs_write_register(hwmgr->device, mmCP_CPC_IC_BASE_HI, reg_data);
0213
0214 return 0;
0215 }
0216
0217 static uint8_t smu8_translate_firmware_enum_to_arg(struct pp_hwmgr *hwmgr,
0218 enum smu8_scratch_entry firmware_enum)
0219 {
0220 uint8_t ret = 0;
0221
0222 switch (firmware_enum) {
0223 case SMU8_SCRATCH_ENTRY_UCODE_ID_SDMA0:
0224 ret = UCODE_ID_SDMA0;
0225 break;
0226 case SMU8_SCRATCH_ENTRY_UCODE_ID_SDMA1:
0227 if (hwmgr->chip_id == CHIP_STONEY)
0228 ret = UCODE_ID_SDMA0;
0229 else
0230 ret = UCODE_ID_SDMA1;
0231 break;
0232 case SMU8_SCRATCH_ENTRY_UCODE_ID_CP_CE:
0233 ret = UCODE_ID_CP_CE;
0234 break;
0235 case SMU8_SCRATCH_ENTRY_UCODE_ID_CP_PFP:
0236 ret = UCODE_ID_CP_PFP;
0237 break;
0238 case SMU8_SCRATCH_ENTRY_UCODE_ID_CP_ME:
0239 ret = UCODE_ID_CP_ME;
0240 break;
0241 case SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1:
0242 ret = UCODE_ID_CP_MEC_JT1;
0243 break;
0244 case SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2:
0245 if (hwmgr->chip_id == CHIP_STONEY)
0246 ret = UCODE_ID_CP_MEC_JT1;
0247 else
0248 ret = UCODE_ID_CP_MEC_JT2;
0249 break;
0250 case SMU8_SCRATCH_ENTRY_UCODE_ID_GMCON_RENG:
0251 ret = UCODE_ID_GMCON_RENG;
0252 break;
0253 case SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_G:
0254 ret = UCODE_ID_RLC_G;
0255 break;
0256 case SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH:
0257 ret = UCODE_ID_RLC_SCRATCH;
0258 break;
0259 case SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM:
0260 ret = UCODE_ID_RLC_SRM_ARAM;
0261 break;
0262 case SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM:
0263 ret = UCODE_ID_RLC_SRM_DRAM;
0264 break;
0265 case SMU8_SCRATCH_ENTRY_UCODE_ID_DMCU_ERAM:
0266 ret = UCODE_ID_DMCU_ERAM;
0267 break;
0268 case SMU8_SCRATCH_ENTRY_UCODE_ID_DMCU_IRAM:
0269 ret = UCODE_ID_DMCU_IRAM;
0270 break;
0271 case SMU8_SCRATCH_ENTRY_UCODE_ID_POWER_PROFILING:
0272 ret = TASK_ARG_INIT_MM_PWR_LOG;
0273 break;
0274 case SMU8_SCRATCH_ENTRY_DATA_ID_SDMA_HALT:
0275 case SMU8_SCRATCH_ENTRY_DATA_ID_SYS_CLOCKGATING:
0276 case SMU8_SCRATCH_ENTRY_DATA_ID_SDMA_RING_REGS:
0277 case SMU8_SCRATCH_ENTRY_DATA_ID_NONGFX_REINIT:
0278 case SMU8_SCRATCH_ENTRY_DATA_ID_SDMA_START:
0279 case SMU8_SCRATCH_ENTRY_DATA_ID_IH_REGISTERS:
0280 ret = TASK_ARG_REG_MMIO;
0281 break;
0282 case SMU8_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE:
0283 ret = TASK_ARG_INIT_CLK_TABLE;
0284 break;
0285 }
0286
0287 return ret;
0288 }
0289
0290 static enum cgs_ucode_id smu8_convert_fw_type_to_cgs(uint32_t fw_type)
0291 {
0292 enum cgs_ucode_id result = CGS_UCODE_ID_MAXIMUM;
0293
0294 switch (fw_type) {
0295 case UCODE_ID_SDMA0:
0296 result = CGS_UCODE_ID_SDMA0;
0297 break;
0298 case UCODE_ID_SDMA1:
0299 result = CGS_UCODE_ID_SDMA1;
0300 break;
0301 case UCODE_ID_CP_CE:
0302 result = CGS_UCODE_ID_CP_CE;
0303 break;
0304 case UCODE_ID_CP_PFP:
0305 result = CGS_UCODE_ID_CP_PFP;
0306 break;
0307 case UCODE_ID_CP_ME:
0308 result = CGS_UCODE_ID_CP_ME;
0309 break;
0310 case UCODE_ID_CP_MEC_JT1:
0311 result = CGS_UCODE_ID_CP_MEC_JT1;
0312 break;
0313 case UCODE_ID_CP_MEC_JT2:
0314 result = CGS_UCODE_ID_CP_MEC_JT2;
0315 break;
0316 case UCODE_ID_RLC_G:
0317 result = CGS_UCODE_ID_RLC_G;
0318 break;
0319 default:
0320 break;
0321 }
0322
0323 return result;
0324 }
0325
0326 static int smu8_smu_populate_single_scratch_task(
0327 struct pp_hwmgr *hwmgr,
0328 enum smu8_scratch_entry fw_enum,
0329 uint8_t type, bool is_last)
0330 {
0331 uint8_t i;
0332 struct smu8_smumgr *smu8_smu = hwmgr->smu_backend;
0333 struct TOC *toc = (struct TOC *)smu8_smu->toc_buffer.kaddr;
0334 struct SMU_Task *task = &toc->tasks[smu8_smu->toc_entry_used_count++];
0335
0336 task->type = type;
0337 task->arg = smu8_translate_firmware_enum_to_arg(hwmgr, fw_enum);
0338 task->next = is_last ? END_OF_TASK_LIST : smu8_smu->toc_entry_used_count;
0339
0340 for (i = 0; i < smu8_smu->scratch_buffer_length; i++)
0341 if (smu8_smu->scratch_buffer[i].firmware_ID == fw_enum)
0342 break;
0343
0344 if (i >= smu8_smu->scratch_buffer_length) {
0345 pr_err("Invalid Firmware Type\n");
0346 return -EINVAL;
0347 }
0348
0349 task->addr.low = lower_32_bits(smu8_smu->scratch_buffer[i].mc_addr);
0350 task->addr.high = upper_32_bits(smu8_smu->scratch_buffer[i].mc_addr);
0351 task->size_bytes = smu8_smu->scratch_buffer[i].data_size;
0352
0353 if (SMU8_SCRATCH_ENTRY_DATA_ID_IH_REGISTERS == fw_enum) {
0354 struct smu8_ih_meta_data *pIHReg_restore =
0355 (struct smu8_ih_meta_data *)smu8_smu->scratch_buffer[i].kaddr;
0356 pIHReg_restore->command =
0357 METADATA_CMD_MODE0 | METADATA_PERFORM_ON_LOAD;
0358 }
0359
0360 return 0;
0361 }
0362
0363 static int smu8_smu_populate_single_ucode_load_task(
0364 struct pp_hwmgr *hwmgr,
0365 enum smu8_scratch_entry fw_enum,
0366 bool is_last)
0367 {
0368 uint8_t i;
0369 struct smu8_smumgr *smu8_smu = hwmgr->smu_backend;
0370 struct TOC *toc = (struct TOC *)smu8_smu->toc_buffer.kaddr;
0371 struct SMU_Task *task = &toc->tasks[smu8_smu->toc_entry_used_count++];
0372
0373 task->type = TASK_TYPE_UCODE_LOAD;
0374 task->arg = smu8_translate_firmware_enum_to_arg(hwmgr, fw_enum);
0375 task->next = is_last ? END_OF_TASK_LIST : smu8_smu->toc_entry_used_count;
0376
0377 for (i = 0; i < smu8_smu->driver_buffer_length; i++)
0378 if (smu8_smu->driver_buffer[i].firmware_ID == fw_enum)
0379 break;
0380
0381 if (i >= smu8_smu->driver_buffer_length) {
0382 pr_err("Invalid Firmware Type\n");
0383 return -EINVAL;
0384 }
0385
0386 task->addr.low = lower_32_bits(smu8_smu->driver_buffer[i].mc_addr);
0387 task->addr.high = upper_32_bits(smu8_smu->driver_buffer[i].mc_addr);
0388 task->size_bytes = smu8_smu->driver_buffer[i].data_size;
0389
0390 return 0;
0391 }
0392
0393 static int smu8_smu_construct_toc_for_rlc_aram_save(struct pp_hwmgr *hwmgr)
0394 {
0395 struct smu8_smumgr *smu8_smu = hwmgr->smu_backend;
0396
0397 smu8_smu->toc_entry_aram = smu8_smu->toc_entry_used_count;
0398 smu8_smu_populate_single_scratch_task(hwmgr,
0399 SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM,
0400 TASK_TYPE_UCODE_SAVE, true);
0401
0402 return 0;
0403 }
0404
0405 static int smu8_smu_initialize_toc_empty_job_list(struct pp_hwmgr *hwmgr)
0406 {
0407 int i;
0408 struct smu8_smumgr *smu8_smu = hwmgr->smu_backend;
0409 struct TOC *toc = (struct TOC *)smu8_smu->toc_buffer.kaddr;
0410
0411 for (i = 0; i < NUM_JOBLIST_ENTRIES; i++)
0412 toc->JobList[i] = (uint8_t)IGNORE_JOB;
0413
0414 return 0;
0415 }
0416
0417 static int smu8_smu_construct_toc_for_vddgfx_enter(struct pp_hwmgr *hwmgr)
0418 {
0419 struct smu8_smumgr *smu8_smu = hwmgr->smu_backend;
0420 struct TOC *toc = (struct TOC *)smu8_smu->toc_buffer.kaddr;
0421
0422 toc->JobList[JOB_GFX_SAVE] = (uint8_t)smu8_smu->toc_entry_used_count;
0423 smu8_smu_populate_single_scratch_task(hwmgr,
0424 SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH,
0425 TASK_TYPE_UCODE_SAVE, false);
0426
0427 smu8_smu_populate_single_scratch_task(hwmgr,
0428 SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM,
0429 TASK_TYPE_UCODE_SAVE, true);
0430
0431 return 0;
0432 }
0433
0434
0435 static int smu8_smu_construct_toc_for_vddgfx_exit(struct pp_hwmgr *hwmgr)
0436 {
0437 struct smu8_smumgr *smu8_smu = hwmgr->smu_backend;
0438 struct TOC *toc = (struct TOC *)smu8_smu->toc_buffer.kaddr;
0439
0440 toc->JobList[JOB_GFX_RESTORE] = (uint8_t)smu8_smu->toc_entry_used_count;
0441
0442 smu8_smu_populate_single_ucode_load_task(hwmgr,
0443 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_CE, false);
0444 smu8_smu_populate_single_ucode_load_task(hwmgr,
0445 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_PFP, false);
0446 smu8_smu_populate_single_ucode_load_task(hwmgr,
0447 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_ME, false);
0448 smu8_smu_populate_single_ucode_load_task(hwmgr,
0449 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, false);
0450
0451 if (hwmgr->chip_id == CHIP_STONEY)
0452 smu8_smu_populate_single_ucode_load_task(hwmgr,
0453 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, false);
0454 else
0455 smu8_smu_populate_single_ucode_load_task(hwmgr,
0456 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2, false);
0457
0458 smu8_smu_populate_single_ucode_load_task(hwmgr,
0459 SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_G, false);
0460
0461
0462 smu8_smu_populate_single_scratch_task(hwmgr,
0463 SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH,
0464 TASK_TYPE_UCODE_LOAD, false);
0465
0466 smu8_smu_populate_single_scratch_task(hwmgr,
0467 SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM,
0468 TASK_TYPE_UCODE_LOAD, false);
0469
0470 smu8_smu_populate_single_scratch_task(hwmgr,
0471 SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM,
0472 TASK_TYPE_UCODE_LOAD, true);
0473
0474 return 0;
0475 }
0476
0477 static int smu8_smu_construct_toc_for_power_profiling(struct pp_hwmgr *hwmgr)
0478 {
0479 struct smu8_smumgr *smu8_smu = hwmgr->smu_backend;
0480
0481 smu8_smu->toc_entry_power_profiling_index = smu8_smu->toc_entry_used_count;
0482
0483 smu8_smu_populate_single_scratch_task(hwmgr,
0484 SMU8_SCRATCH_ENTRY_UCODE_ID_POWER_PROFILING,
0485 TASK_TYPE_INITIALIZE, true);
0486 return 0;
0487 }
0488
0489 static int smu8_smu_construct_toc_for_bootup(struct pp_hwmgr *hwmgr)
0490 {
0491 struct smu8_smumgr *smu8_smu = hwmgr->smu_backend;
0492
0493 smu8_smu->toc_entry_initialize_index = smu8_smu->toc_entry_used_count;
0494
0495 smu8_smu_populate_single_ucode_load_task(hwmgr,
0496 SMU8_SCRATCH_ENTRY_UCODE_ID_SDMA0, false);
0497 if (hwmgr->chip_id != CHIP_STONEY)
0498 smu8_smu_populate_single_ucode_load_task(hwmgr,
0499 SMU8_SCRATCH_ENTRY_UCODE_ID_SDMA1, false);
0500 smu8_smu_populate_single_ucode_load_task(hwmgr,
0501 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_CE, false);
0502 smu8_smu_populate_single_ucode_load_task(hwmgr,
0503 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_PFP, false);
0504 smu8_smu_populate_single_ucode_load_task(hwmgr,
0505 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_ME, false);
0506 smu8_smu_populate_single_ucode_load_task(hwmgr,
0507 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, false);
0508 if (hwmgr->chip_id != CHIP_STONEY)
0509 smu8_smu_populate_single_ucode_load_task(hwmgr,
0510 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2, false);
0511 smu8_smu_populate_single_ucode_load_task(hwmgr,
0512 SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_G, true);
0513
0514 return 0;
0515 }
0516
0517 static int smu8_smu_construct_toc_for_clock_table(struct pp_hwmgr *hwmgr)
0518 {
0519 struct smu8_smumgr *smu8_smu = hwmgr->smu_backend;
0520
0521 smu8_smu->toc_entry_clock_table = smu8_smu->toc_entry_used_count;
0522
0523 smu8_smu_populate_single_scratch_task(hwmgr,
0524 SMU8_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE,
0525 TASK_TYPE_INITIALIZE, true);
0526
0527 return 0;
0528 }
0529
0530 static int smu8_smu_construct_toc(struct pp_hwmgr *hwmgr)
0531 {
0532 struct smu8_smumgr *smu8_smu = hwmgr->smu_backend;
0533
0534 smu8_smu->toc_entry_used_count = 0;
0535 smu8_smu_initialize_toc_empty_job_list(hwmgr);
0536 smu8_smu_construct_toc_for_rlc_aram_save(hwmgr);
0537 smu8_smu_construct_toc_for_vddgfx_enter(hwmgr);
0538 smu8_smu_construct_toc_for_vddgfx_exit(hwmgr);
0539 smu8_smu_construct_toc_for_power_profiling(hwmgr);
0540 smu8_smu_construct_toc_for_bootup(hwmgr);
0541 smu8_smu_construct_toc_for_clock_table(hwmgr);
0542
0543 return 0;
0544 }
0545
0546 static int smu8_smu_populate_firmware_entries(struct pp_hwmgr *hwmgr)
0547 {
0548 struct smu8_smumgr *smu8_smu = hwmgr->smu_backend;
0549 uint32_t firmware_type;
0550 uint32_t i;
0551 int ret;
0552 enum cgs_ucode_id ucode_id;
0553 struct cgs_firmware_info info = {0};
0554
0555 smu8_smu->driver_buffer_length = 0;
0556
0557 for (i = 0; i < ARRAY_SIZE(firmware_list); i++) {
0558
0559 firmware_type = smu8_translate_firmware_enum_to_arg(hwmgr,
0560 firmware_list[i]);
0561
0562 ucode_id = smu8_convert_fw_type_to_cgs(firmware_type);
0563
0564 ret = cgs_get_firmware_info(hwmgr->device,
0565 ucode_id, &info);
0566
0567 if (ret == 0) {
0568 smu8_smu->driver_buffer[i].mc_addr = info.mc_addr;
0569
0570 smu8_smu->driver_buffer[i].data_size = info.image_size;
0571
0572 smu8_smu->driver_buffer[i].firmware_ID = firmware_list[i];
0573 smu8_smu->driver_buffer_length++;
0574 }
0575 }
0576
0577 return 0;
0578 }
0579
0580 static int smu8_smu_populate_single_scratch_entry(
0581 struct pp_hwmgr *hwmgr,
0582 enum smu8_scratch_entry scratch_type,
0583 uint32_t ulsize_byte,
0584 struct smu8_buffer_entry *entry)
0585 {
0586 struct smu8_smumgr *smu8_smu = hwmgr->smu_backend;
0587 uint32_t ulsize_aligned = SIZE_ALIGN_32(ulsize_byte);
0588
0589 entry->data_size = ulsize_byte;
0590 entry->kaddr = (char *) smu8_smu->smu_buffer.kaddr +
0591 smu8_smu->smu_buffer_used_bytes;
0592 entry->mc_addr = smu8_smu->smu_buffer.mc_addr + smu8_smu->smu_buffer_used_bytes;
0593 entry->firmware_ID = scratch_type;
0594
0595 smu8_smu->smu_buffer_used_bytes += ulsize_aligned;
0596
0597 return 0;
0598 }
0599
0600 static int smu8_download_pptable_settings(struct pp_hwmgr *hwmgr, void **table)
0601 {
0602 struct smu8_smumgr *smu8_smu = hwmgr->smu_backend;
0603 unsigned long i;
0604
0605 for (i = 0; i < smu8_smu->scratch_buffer_length; i++) {
0606 if (smu8_smu->scratch_buffer[i].firmware_ID
0607 == SMU8_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE)
0608 break;
0609 }
0610
0611 *table = (struct SMU8_Fusion_ClkTable *)smu8_smu->scratch_buffer[i].kaddr;
0612
0613 smum_send_msg_to_smc_with_parameter(hwmgr,
0614 PPSMC_MSG_SetClkTableAddrHi,
0615 upper_32_bits(smu8_smu->scratch_buffer[i].mc_addr),
0616 NULL);
0617
0618 smum_send_msg_to_smc_with_parameter(hwmgr,
0619 PPSMC_MSG_SetClkTableAddrLo,
0620 lower_32_bits(smu8_smu->scratch_buffer[i].mc_addr),
0621 NULL);
0622
0623 smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_ExecuteJob,
0624 smu8_smu->toc_entry_clock_table,
0625 NULL);
0626
0627 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ClkTableXferToDram, NULL);
0628
0629 return 0;
0630 }
0631
0632 static int smu8_upload_pptable_settings(struct pp_hwmgr *hwmgr)
0633 {
0634 struct smu8_smumgr *smu8_smu = hwmgr->smu_backend;
0635 unsigned long i;
0636
0637 for (i = 0; i < smu8_smu->scratch_buffer_length; i++) {
0638 if (smu8_smu->scratch_buffer[i].firmware_ID
0639 == SMU8_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE)
0640 break;
0641 }
0642
0643 smum_send_msg_to_smc_with_parameter(hwmgr,
0644 PPSMC_MSG_SetClkTableAddrHi,
0645 upper_32_bits(smu8_smu->scratch_buffer[i].mc_addr),
0646 NULL);
0647
0648 smum_send_msg_to_smc_with_parameter(hwmgr,
0649 PPSMC_MSG_SetClkTableAddrLo,
0650 lower_32_bits(smu8_smu->scratch_buffer[i].mc_addr),
0651 NULL);
0652
0653 smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_ExecuteJob,
0654 smu8_smu->toc_entry_clock_table,
0655 NULL);
0656
0657 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ClkTableXferToSmu, NULL);
0658
0659 return 0;
0660 }
0661
0662 static int smu8_request_smu_load_fw(struct pp_hwmgr *hwmgr)
0663 {
0664 struct smu8_smumgr *smu8_smu = hwmgr->smu_backend;
0665 uint32_t smc_address;
0666 uint32_t fw_to_check = 0;
0667 int ret;
0668
0669 amdgpu_ucode_init_bo(hwmgr->adev);
0670
0671 smu8_smu_populate_firmware_entries(hwmgr);
0672
0673 smu8_smu_construct_toc(hwmgr);
0674
0675 smc_address = SMU8_FIRMWARE_HEADER_LOCATION +
0676 offsetof(struct SMU8_Firmware_Header, UcodeLoadStatus);
0677
0678 smu8_write_smc_sram_dword(hwmgr, smc_address, 0, smc_address+4);
0679
0680 smum_send_msg_to_smc_with_parameter(hwmgr,
0681 PPSMC_MSG_DriverDramAddrHi,
0682 upper_32_bits(smu8_smu->toc_buffer.mc_addr),
0683 NULL);
0684
0685 smum_send_msg_to_smc_with_parameter(hwmgr,
0686 PPSMC_MSG_DriverDramAddrLo,
0687 lower_32_bits(smu8_smu->toc_buffer.mc_addr),
0688 NULL);
0689
0690 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_InitJobs, NULL);
0691
0692 smum_send_msg_to_smc_with_parameter(hwmgr,
0693 PPSMC_MSG_ExecuteJob,
0694 smu8_smu->toc_entry_aram,
0695 NULL);
0696 smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_ExecuteJob,
0697 smu8_smu->toc_entry_power_profiling_index,
0698 NULL);
0699
0700 smum_send_msg_to_smc_with_parameter(hwmgr,
0701 PPSMC_MSG_ExecuteJob,
0702 smu8_smu->toc_entry_initialize_index,
0703 NULL);
0704
0705 fw_to_check = UCODE_ID_RLC_G_MASK |
0706 UCODE_ID_SDMA0_MASK |
0707 UCODE_ID_SDMA1_MASK |
0708 UCODE_ID_CP_CE_MASK |
0709 UCODE_ID_CP_ME_MASK |
0710 UCODE_ID_CP_PFP_MASK |
0711 UCODE_ID_CP_MEC_JT1_MASK |
0712 UCODE_ID_CP_MEC_JT2_MASK;
0713
0714 if (hwmgr->chip_id == CHIP_STONEY)
0715 fw_to_check &= ~(UCODE_ID_SDMA1_MASK | UCODE_ID_CP_MEC_JT2_MASK);
0716
0717 ret = smu8_check_fw_load_finish(hwmgr, fw_to_check);
0718 if (ret) {
0719 pr_err("SMU firmware load failed\n");
0720 return ret;
0721 }
0722
0723 ret = smu8_load_mec_firmware(hwmgr);
0724 if (ret) {
0725 pr_err("Mec Firmware load failed\n");
0726 return ret;
0727 }
0728
0729 return 0;
0730 }
0731
0732 static int smu8_start_smu(struct pp_hwmgr *hwmgr)
0733 {
0734 struct amdgpu_device *adev;
0735
0736 uint32_t index = SMN_MP1_SRAM_START_ADDR +
0737 SMU8_FIRMWARE_HEADER_LOCATION +
0738 offsetof(struct SMU8_Firmware_Header, Version);
0739
0740 if (hwmgr == NULL || hwmgr->device == NULL)
0741 return -EINVAL;
0742
0743 adev = hwmgr->adev;
0744
0745 cgs_write_register(hwmgr->device, mmMP0PUB_IND_INDEX, index);
0746 hwmgr->smu_version = cgs_read_register(hwmgr->device, mmMP0PUB_IND_DATA);
0747 pr_info("smu version %02d.%02d.%02d\n",
0748 ((hwmgr->smu_version >> 16) & 0xFF),
0749 ((hwmgr->smu_version >> 8) & 0xFF),
0750 (hwmgr->smu_version & 0xFF));
0751 adev->pm.fw_version = hwmgr->smu_version >> 8;
0752
0753 return smu8_request_smu_load_fw(hwmgr);
0754 }
0755
0756 static int smu8_smu_init(struct pp_hwmgr *hwmgr)
0757 {
0758 int ret = 0;
0759 struct smu8_smumgr *smu8_smu;
0760
0761 smu8_smu = kzalloc(sizeof(struct smu8_smumgr), GFP_KERNEL);
0762 if (smu8_smu == NULL)
0763 return -ENOMEM;
0764
0765 hwmgr->smu_backend = smu8_smu;
0766
0767 smu8_smu->toc_buffer.data_size = 4096;
0768 smu8_smu->smu_buffer.data_size =
0769 ALIGN(UCODE_ID_RLC_SCRATCH_SIZE_BYTE, 32) +
0770 ALIGN(UCODE_ID_RLC_SRM_ARAM_SIZE_BYTE, 32) +
0771 ALIGN(UCODE_ID_RLC_SRM_DRAM_SIZE_BYTE, 32) +
0772 ALIGN(sizeof(struct SMU8_MultimediaPowerLogData), 32) +
0773 ALIGN(sizeof(struct SMU8_Fusion_ClkTable), 32);
0774
0775 ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
0776 smu8_smu->toc_buffer.data_size,
0777 PAGE_SIZE,
0778 AMDGPU_GEM_DOMAIN_VRAM,
0779 &smu8_smu->toc_buffer.handle,
0780 &smu8_smu->toc_buffer.mc_addr,
0781 &smu8_smu->toc_buffer.kaddr);
0782 if (ret)
0783 goto err2;
0784
0785 ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
0786 smu8_smu->smu_buffer.data_size,
0787 PAGE_SIZE,
0788 AMDGPU_GEM_DOMAIN_VRAM,
0789 &smu8_smu->smu_buffer.handle,
0790 &smu8_smu->smu_buffer.mc_addr,
0791 &smu8_smu->smu_buffer.kaddr);
0792 if (ret)
0793 goto err1;
0794
0795 if (0 != smu8_smu_populate_single_scratch_entry(hwmgr,
0796 SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH,
0797 UCODE_ID_RLC_SCRATCH_SIZE_BYTE,
0798 &smu8_smu->scratch_buffer[smu8_smu->scratch_buffer_length++])) {
0799 pr_err("Error when Populate Firmware Entry.\n");
0800 goto err0;
0801 }
0802
0803 if (0 != smu8_smu_populate_single_scratch_entry(hwmgr,
0804 SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM,
0805 UCODE_ID_RLC_SRM_ARAM_SIZE_BYTE,
0806 &smu8_smu->scratch_buffer[smu8_smu->scratch_buffer_length++])) {
0807 pr_err("Error when Populate Firmware Entry.\n");
0808 goto err0;
0809 }
0810 if (0 != smu8_smu_populate_single_scratch_entry(hwmgr,
0811 SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM,
0812 UCODE_ID_RLC_SRM_DRAM_SIZE_BYTE,
0813 &smu8_smu->scratch_buffer[smu8_smu->scratch_buffer_length++])) {
0814 pr_err("Error when Populate Firmware Entry.\n");
0815 goto err0;
0816 }
0817
0818 if (0 != smu8_smu_populate_single_scratch_entry(hwmgr,
0819 SMU8_SCRATCH_ENTRY_UCODE_ID_POWER_PROFILING,
0820 sizeof(struct SMU8_MultimediaPowerLogData),
0821 &smu8_smu->scratch_buffer[smu8_smu->scratch_buffer_length++])) {
0822 pr_err("Error when Populate Firmware Entry.\n");
0823 goto err0;
0824 }
0825
0826 if (0 != smu8_smu_populate_single_scratch_entry(hwmgr,
0827 SMU8_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE,
0828 sizeof(struct SMU8_Fusion_ClkTable),
0829 &smu8_smu->scratch_buffer[smu8_smu->scratch_buffer_length++])) {
0830 pr_err("Error when Populate Firmware Entry.\n");
0831 goto err0;
0832 }
0833
0834 return 0;
0835
0836 err0:
0837 amdgpu_bo_free_kernel(&smu8_smu->smu_buffer.handle,
0838 &smu8_smu->smu_buffer.mc_addr,
0839 &smu8_smu->smu_buffer.kaddr);
0840 err1:
0841 amdgpu_bo_free_kernel(&smu8_smu->toc_buffer.handle,
0842 &smu8_smu->toc_buffer.mc_addr,
0843 &smu8_smu->toc_buffer.kaddr);
0844 err2:
0845 kfree(smu8_smu);
0846 return -EINVAL;
0847 }
0848
0849 static int smu8_smu_fini(struct pp_hwmgr *hwmgr)
0850 {
0851 struct smu8_smumgr *smu8_smu;
0852
0853 if (hwmgr == NULL || hwmgr->device == NULL)
0854 return -EINVAL;
0855
0856 smu8_smu = hwmgr->smu_backend;
0857 if (smu8_smu) {
0858 amdgpu_bo_free_kernel(&smu8_smu->toc_buffer.handle,
0859 &smu8_smu->toc_buffer.mc_addr,
0860 &smu8_smu->toc_buffer.kaddr);
0861 amdgpu_bo_free_kernel(&smu8_smu->smu_buffer.handle,
0862 &smu8_smu->smu_buffer.mc_addr,
0863 &smu8_smu->smu_buffer.kaddr);
0864 kfree(smu8_smu);
0865 }
0866
0867 return 0;
0868 }
0869
0870 static bool smu8_dpm_check_smu_features(struct pp_hwmgr *hwmgr,
0871 unsigned long check_feature)
0872 {
0873 int result;
0874 uint32_t features;
0875
0876 result = smum_send_msg_to_smc_with_parameter(hwmgr,
0877 PPSMC_MSG_GetFeatureStatus,
0878 0,
0879 &features);
0880 if (result == 0) {
0881 if (features & check_feature)
0882 return true;
0883 }
0884
0885 return false;
0886 }
0887
0888 static bool smu8_is_dpm_running(struct pp_hwmgr *hwmgr)
0889 {
0890 if (smu8_dpm_check_smu_features(hwmgr, SMU_EnabledFeatureScoreboard_SclkDpmOn))
0891 return true;
0892 return false;
0893 }
0894
0895 const struct pp_smumgr_func smu8_smu_funcs = {
0896 .name = "smu8_smu",
0897 .smu_init = smu8_smu_init,
0898 .smu_fini = smu8_smu_fini,
0899 .start_smu = smu8_start_smu,
0900 .check_fw_load_finish = smu8_check_fw_load_finish,
0901 .request_smu_load_fw = NULL,
0902 .request_smu_load_specific_fw = NULL,
0903 .get_argument = smu8_get_argument,
0904 .send_msg_to_smc = smu8_send_msg_to_smc,
0905 .send_msg_to_smc_with_parameter = smu8_send_msg_to_smc_with_parameter,
0906 .download_pptable_settings = smu8_download_pptable_settings,
0907 .upload_pptable_settings = smu8_upload_pptable_settings,
0908 .is_dpm_running = smu8_is_dpm_running,
0909 };
0910