1 /* 2 * Copyright 2015 Advanced Micro Devices, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 * 22 */ 23 24 #include <linux/delay.h> 25 #include <linux/gfp.h> 26 #include <linux/kernel.h> 27 #include <linux/ktime.h> 28 #include <linux/slab.h> 29 #include <linux/types.h> 30 31 #include "cgs_common.h" 32 #include "smu/smu_8_0_d.h" 33 #include "smu/smu_8_0_sh_mask.h" 34 #include "smu8.h" 35 #include "smu8_fusion.h" 36 #include "smu8_smumgr.h" 37 #include "cz_ppsmc.h" 38 #include "smu_ucode_xfer_cz.h" 39 #include "gca/gfx_8_0_d.h" 40 #include "gca/gfx_8_0_sh_mask.h" 41 #include "smumgr.h" 42 43 #define SIZE_ALIGN_32(x) (((x) + 31) / 32 * 32) 44 45 static const enum smu8_scratch_entry firmware_list[] = { 46 SMU8_SCRATCH_ENTRY_UCODE_ID_SDMA0, 47 SMU8_SCRATCH_ENTRY_UCODE_ID_SDMA1, 48 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_CE, 49 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_PFP, 50 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_ME, 51 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, 52 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2, 53 SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_G, 54 }; 55 56 static uint32_t smu8_get_argument(struct pp_hwmgr *hwmgr) 57 { 58 if (hwmgr == NULL || hwmgr->device == NULL) 59 return 0; 60 61 return cgs_read_register(hwmgr->device, 62 mmSMU_MP1_SRBM2P_ARG_0); 63 } 64 65 /* Send a message to the SMC, and wait for its response.*/ 66 static int smu8_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr, 67 uint16_t msg, uint32_t parameter) 68 { 69 int result = 0; 70 ktime_t t_start; 71 s64 elapsed_us; 72 73 if (hwmgr == NULL || hwmgr->device == NULL) 74 return -EINVAL; 75 76 result = PHM_WAIT_FIELD_UNEQUAL(hwmgr, 77 SMU_MP1_SRBM2P_RESP_0, CONTENT, 0); 78 if (result != 0) { 79 /* Read the last message to SMU, to report actual cause */ 80 uint32_t val = cgs_read_register(hwmgr->device, 81 mmSMU_MP1_SRBM2P_MSG_0); 82 pr_err("%s(0x%04x) aborted; SMU still servicing msg (0x%04x)\n", 83 __func__, msg, val); 84 return result; 85 } 86 t_start = ktime_get(); 87 88 cgs_write_register(hwmgr->device, mmSMU_MP1_SRBM2P_ARG_0, parameter); 89 90 cgs_write_register(hwmgr->device, mmSMU_MP1_SRBM2P_RESP_0, 0); 91 cgs_write_register(hwmgr->device, mmSMU_MP1_SRBM2P_MSG_0, msg); 92 93 result = PHM_WAIT_FIELD_UNEQUAL(hwmgr, 94 SMU_MP1_SRBM2P_RESP_0, CONTENT, 0); 95 96 elapsed_us = ktime_us_delta(ktime_get(), t_start); 97 98 WARN(result, "%s(0x%04x, %#x) timed out after %lld us\n", 99 __func__, msg, parameter, elapsed_us); 100 101 return result; 102 } 103 104 static int smu8_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg) 105 { 106 return smu8_send_msg_to_smc_with_parameter(hwmgr, msg, 0); 107 } 108 109 static int smu8_set_smc_sram_address(struct pp_hwmgr *hwmgr, 110 uint32_t smc_address, uint32_t limit) 111 { 112 if (hwmgr == NULL || hwmgr->device == NULL) 113 return -EINVAL; 114 115 if (0 != (3 & smc_address)) { 116 pr_err("SMC address must be 4 byte aligned\n"); 117 return -EINVAL; 118 } 119 120 if (limit <= (smc_address + 3)) { 121 pr_err("SMC address beyond the SMC RAM area\n"); 122 return -EINVAL; 123 } 124 125 cgs_write_register(hwmgr->device, mmMP0PUB_IND_INDEX_0, 126 SMN_MP1_SRAM_START_ADDR + smc_address); 127 128 return 0; 129 } 130 131 static int smu8_write_smc_sram_dword(struct pp_hwmgr *hwmgr, 132 uint32_t smc_address, uint32_t value, uint32_t limit) 133 { 134 int result; 135 136 if (hwmgr == NULL || hwmgr->device == NULL) 137 return -EINVAL; 138 139 result = smu8_set_smc_sram_address(hwmgr, smc_address, limit); 140 if (!result) 141 cgs_write_register(hwmgr->device, mmMP0PUB_IND_DATA_0, value); 142 143 return result; 144 } 145 146 static int smu8_check_fw_load_finish(struct pp_hwmgr *hwmgr, 147 uint32_t firmware) 148 { 149 int i; 150 uint32_t index = SMN_MP1_SRAM_START_ADDR + 151 SMU8_FIRMWARE_HEADER_LOCATION + 152 offsetof(struct SMU8_Firmware_Header, UcodeLoadStatus); 153 154 if (hwmgr == NULL || hwmgr->device == NULL) 155 return -EINVAL; 156 157 cgs_write_register(hwmgr->device, mmMP0PUB_IND_INDEX, index); 158 159 for (i = 0; i < hwmgr->usec_timeout; i++) { 160 if (firmware == 161 (cgs_read_register(hwmgr->device, mmMP0PUB_IND_DATA) & firmware)) 162 break; 163 udelay(1); 164 } 165 166 if (i >= hwmgr->usec_timeout) { 167 pr_err("SMU check loaded firmware failed.\n"); 168 return -EINVAL; 169 } 170 171 return 0; 172 } 173 174 static int smu8_load_mec_firmware(struct pp_hwmgr *hwmgr) 175 { 176 uint32_t reg_data; 177 uint32_t tmp; 178 int ret = 0; 179 struct cgs_firmware_info info = {0}; 180 181 if (hwmgr == NULL || hwmgr->device == NULL) 182 return -EINVAL; 183 184 ret = cgs_get_firmware_info(hwmgr->device, 185 CGS_UCODE_ID_CP_MEC, &info); 186 187 if (ret) 188 return -EINVAL; 189 190 /* Disable MEC parsing/prefetching */ 191 tmp = cgs_read_register(hwmgr->device, 192 mmCP_MEC_CNTL); 193 tmp = PHM_SET_FIELD(tmp, CP_MEC_CNTL, MEC_ME1_HALT, 1); 194 tmp = PHM_SET_FIELD(tmp, CP_MEC_CNTL, MEC_ME2_HALT, 1); 195 cgs_write_register(hwmgr->device, mmCP_MEC_CNTL, tmp); 196 197 tmp = cgs_read_register(hwmgr->device, 198 mmCP_CPC_IC_BASE_CNTL); 199 200 tmp = PHM_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, VMID, 0); 201 tmp = PHM_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, ATC, 0); 202 tmp = PHM_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, CACHE_POLICY, 0); 203 tmp = PHM_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, MTYPE, 1); 204 cgs_write_register(hwmgr->device, mmCP_CPC_IC_BASE_CNTL, tmp); 205 206 reg_data = lower_32_bits(info.mc_addr) & 207 PHM_FIELD_MASK(CP_CPC_IC_BASE_LO, IC_BASE_LO); 208 cgs_write_register(hwmgr->device, mmCP_CPC_IC_BASE_LO, reg_data); 209 210 reg_data = upper_32_bits(info.mc_addr) & 211 PHM_FIELD_MASK(CP_CPC_IC_BASE_HI, IC_BASE_HI); 212 cgs_write_register(hwmgr->device, mmCP_CPC_IC_BASE_HI, reg_data); 213 214 return 0; 215 } 216 217 static uint8_t smu8_translate_firmware_enum_to_arg(struct pp_hwmgr *hwmgr, 218 enum smu8_scratch_entry firmware_enum) 219 { 220 uint8_t ret = 0; 221 222 switch (firmware_enum) { 223 case SMU8_SCRATCH_ENTRY_UCODE_ID_SDMA0: 224 ret = UCODE_ID_SDMA0; 225 break; 226 case SMU8_SCRATCH_ENTRY_UCODE_ID_SDMA1: 227 if (hwmgr->chip_id == CHIP_STONEY) 228 ret = UCODE_ID_SDMA0; 229 else 230 ret = UCODE_ID_SDMA1; 231 break; 232 case SMU8_SCRATCH_ENTRY_UCODE_ID_CP_CE: 233 ret = UCODE_ID_CP_CE; 234 break; 235 case SMU8_SCRATCH_ENTRY_UCODE_ID_CP_PFP: 236 ret = UCODE_ID_CP_PFP; 237 break; 238 case SMU8_SCRATCH_ENTRY_UCODE_ID_CP_ME: 239 ret = UCODE_ID_CP_ME; 240 break; 241 case SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1: 242 ret = UCODE_ID_CP_MEC_JT1; 243 break; 244 case SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2: 245 if (hwmgr->chip_id == CHIP_STONEY) 246 ret = UCODE_ID_CP_MEC_JT1; 247 else 248 ret = UCODE_ID_CP_MEC_JT2; 249 break; 250 case SMU8_SCRATCH_ENTRY_UCODE_ID_GMCON_RENG: 251 ret = UCODE_ID_GMCON_RENG; 252 break; 253 case SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_G: 254 ret = UCODE_ID_RLC_G; 255 break; 256 case SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH: 257 ret = UCODE_ID_RLC_SCRATCH; 258 break; 259 case SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM: 260 ret = UCODE_ID_RLC_SRM_ARAM; 261 break; 262 case SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM: 263 ret = UCODE_ID_RLC_SRM_DRAM; 264 break; 265 case SMU8_SCRATCH_ENTRY_UCODE_ID_DMCU_ERAM: 266 ret = UCODE_ID_DMCU_ERAM; 267 break; 268 case SMU8_SCRATCH_ENTRY_UCODE_ID_DMCU_IRAM: 269 ret = UCODE_ID_DMCU_IRAM; 270 break; 271 case SMU8_SCRATCH_ENTRY_UCODE_ID_POWER_PROFILING: 272 ret = TASK_ARG_INIT_MM_PWR_LOG; 273 break; 274 case SMU8_SCRATCH_ENTRY_DATA_ID_SDMA_HALT: 275 case SMU8_SCRATCH_ENTRY_DATA_ID_SYS_CLOCKGATING: 276 case SMU8_SCRATCH_ENTRY_DATA_ID_SDMA_RING_REGS: 277 case SMU8_SCRATCH_ENTRY_DATA_ID_NONGFX_REINIT: 278 case SMU8_SCRATCH_ENTRY_DATA_ID_SDMA_START: 279 case SMU8_SCRATCH_ENTRY_DATA_ID_IH_REGISTERS: 280 ret = TASK_ARG_REG_MMIO; 281 break; 282 case SMU8_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE: 283 ret = TASK_ARG_INIT_CLK_TABLE; 284 break; 285 } 286 287 return ret; 288 } 289 290 static enum cgs_ucode_id smu8_convert_fw_type_to_cgs(uint32_t fw_type) 291 { 292 enum cgs_ucode_id result = CGS_UCODE_ID_MAXIMUM; 293 294 switch (fw_type) { 295 case UCODE_ID_SDMA0: 296 result = CGS_UCODE_ID_SDMA0; 297 break; 298 case UCODE_ID_SDMA1: 299 result = CGS_UCODE_ID_SDMA1; 300 break; 301 case UCODE_ID_CP_CE: 302 result = CGS_UCODE_ID_CP_CE; 303 break; 304 case UCODE_ID_CP_PFP: 305 result = CGS_UCODE_ID_CP_PFP; 306 break; 307 case UCODE_ID_CP_ME: 308 result = CGS_UCODE_ID_CP_ME; 309 break; 310 case UCODE_ID_CP_MEC_JT1: 311 result = CGS_UCODE_ID_CP_MEC_JT1; 312 break; 313 case UCODE_ID_CP_MEC_JT2: 314 result = CGS_UCODE_ID_CP_MEC_JT2; 315 break; 316 case UCODE_ID_RLC_G: 317 result = CGS_UCODE_ID_RLC_G; 318 break; 319 default: 320 break; 321 } 322 323 return result; 324 } 325 326 static int smu8_smu_populate_single_scratch_task( 327 struct pp_hwmgr *hwmgr, 328 enum smu8_scratch_entry fw_enum, 329 uint8_t type, bool is_last) 330 { 331 uint8_t i; 332 struct smu8_smumgr *smu8_smu = hwmgr->smu_backend; 333 struct TOC *toc = (struct TOC *)smu8_smu->toc_buffer.kaddr; 334 struct SMU_Task *task = &toc->tasks[smu8_smu->toc_entry_used_count++]; 335 336 task->type = type; 337 task->arg = smu8_translate_firmware_enum_to_arg(hwmgr, fw_enum); 338 task->next = is_last ? END_OF_TASK_LIST : smu8_smu->toc_entry_used_count; 339 340 for (i = 0; i < smu8_smu->scratch_buffer_length; i++) 341 if (smu8_smu->scratch_buffer[i].firmware_ID == fw_enum) 342 break; 343 344 if (i >= smu8_smu->scratch_buffer_length) { 345 pr_err("Invalid Firmware Type\n"); 346 return -EINVAL; 347 } 348 349 task->addr.low = lower_32_bits(smu8_smu->scratch_buffer[i].mc_addr); 350 task->addr.high = upper_32_bits(smu8_smu->scratch_buffer[i].mc_addr); 351 task->size_bytes = smu8_smu->scratch_buffer[i].data_size; 352 353 if (SMU8_SCRATCH_ENTRY_DATA_ID_IH_REGISTERS == fw_enum) { 354 struct smu8_ih_meta_data *pIHReg_restore = 355 (struct smu8_ih_meta_data *)smu8_smu->scratch_buffer[i].kaddr; 356 pIHReg_restore->command = 357 METADATA_CMD_MODE0 | METADATA_PERFORM_ON_LOAD; 358 } 359 360 return 0; 361 } 362 363 static int smu8_smu_populate_single_ucode_load_task( 364 struct pp_hwmgr *hwmgr, 365 enum smu8_scratch_entry fw_enum, 366 bool is_last) 367 { 368 uint8_t i; 369 struct smu8_smumgr *smu8_smu = hwmgr->smu_backend; 370 struct TOC *toc = (struct TOC *)smu8_smu->toc_buffer.kaddr; 371 struct SMU_Task *task = &toc->tasks[smu8_smu->toc_entry_used_count++]; 372 373 task->type = TASK_TYPE_UCODE_LOAD; 374 task->arg = smu8_translate_firmware_enum_to_arg(hwmgr, fw_enum); 375 task->next = is_last ? END_OF_TASK_LIST : smu8_smu->toc_entry_used_count; 376 377 for (i = 0; i < smu8_smu->driver_buffer_length; i++) 378 if (smu8_smu->driver_buffer[i].firmware_ID == fw_enum) 379 break; 380 381 if (i >= smu8_smu->driver_buffer_length) { 382 pr_err("Invalid Firmware Type\n"); 383 return -EINVAL; 384 } 385 386 task->addr.low = lower_32_bits(smu8_smu->driver_buffer[i].mc_addr); 387 task->addr.high = upper_32_bits(smu8_smu->driver_buffer[i].mc_addr); 388 task->size_bytes = smu8_smu->driver_buffer[i].data_size; 389 390 return 0; 391 } 392 393 static int smu8_smu_construct_toc_for_rlc_aram_save(struct pp_hwmgr *hwmgr) 394 { 395 struct smu8_smumgr *smu8_smu = hwmgr->smu_backend; 396 397 smu8_smu->toc_entry_aram = smu8_smu->toc_entry_used_count; 398 smu8_smu_populate_single_scratch_task(hwmgr, 399 SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM, 400 TASK_TYPE_UCODE_SAVE, true); 401 402 return 0; 403 } 404 405 static int smu8_smu_initialize_toc_empty_job_list(struct pp_hwmgr *hwmgr) 406 { 407 int i; 408 struct smu8_smumgr *smu8_smu = hwmgr->smu_backend; 409 struct TOC *toc = (struct TOC *)smu8_smu->toc_buffer.kaddr; 410 411 for (i = 0; i < NUM_JOBLIST_ENTRIES; i++) 412 toc->JobList[i] = (uint8_t)IGNORE_JOB; 413 414 return 0; 415 } 416 417 static int smu8_smu_construct_toc_for_vddgfx_enter(struct pp_hwmgr *hwmgr) 418 { 419 struct smu8_smumgr *smu8_smu = hwmgr->smu_backend; 420 struct TOC *toc = (struct TOC *)smu8_smu->toc_buffer.kaddr; 421 422 toc->JobList[JOB_GFX_SAVE] = (uint8_t)smu8_smu->toc_entry_used_count; 423 smu8_smu_populate_single_scratch_task(hwmgr, 424 SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH, 425 TASK_TYPE_UCODE_SAVE, false); 426 427 smu8_smu_populate_single_scratch_task(hwmgr, 428 SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM, 429 TASK_TYPE_UCODE_SAVE, true); 430 431 return 0; 432 } 433 434 435 static int smu8_smu_construct_toc_for_vddgfx_exit(struct pp_hwmgr *hwmgr) 436 { 437 struct smu8_smumgr *smu8_smu = hwmgr->smu_backend; 438 struct TOC *toc = (struct TOC *)smu8_smu->toc_buffer.kaddr; 439 440 toc->JobList[JOB_GFX_RESTORE] = (uint8_t)smu8_smu->toc_entry_used_count; 441 442 smu8_smu_populate_single_ucode_load_task(hwmgr, 443 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_CE, false); 444 smu8_smu_populate_single_ucode_load_task(hwmgr, 445 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_PFP, false); 446 smu8_smu_populate_single_ucode_load_task(hwmgr, 447 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_ME, false); 448 smu8_smu_populate_single_ucode_load_task(hwmgr, 449 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, false); 450 451 if (hwmgr->chip_id == CHIP_STONEY) 452 smu8_smu_populate_single_ucode_load_task(hwmgr, 453 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, false); 454 else 455 smu8_smu_populate_single_ucode_load_task(hwmgr, 456 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2, false); 457 458 smu8_smu_populate_single_ucode_load_task(hwmgr, 459 SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_G, false); 460 461 /* populate scratch */ 462 smu8_smu_populate_single_scratch_task(hwmgr, 463 SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH, 464 TASK_TYPE_UCODE_LOAD, false); 465 466 smu8_smu_populate_single_scratch_task(hwmgr, 467 SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM, 468 TASK_TYPE_UCODE_LOAD, false); 469 470 smu8_smu_populate_single_scratch_task(hwmgr, 471 SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM, 472 TASK_TYPE_UCODE_LOAD, true); 473 474 return 0; 475 } 476 477 static int smu8_smu_construct_toc_for_power_profiling(struct pp_hwmgr *hwmgr) 478 { 479 struct smu8_smumgr *smu8_smu = hwmgr->smu_backend; 480 481 smu8_smu->toc_entry_power_profiling_index = smu8_smu->toc_entry_used_count; 482 483 smu8_smu_populate_single_scratch_task(hwmgr, 484 SMU8_SCRATCH_ENTRY_UCODE_ID_POWER_PROFILING, 485 TASK_TYPE_INITIALIZE, true); 486 return 0; 487 } 488 489 static int smu8_smu_construct_toc_for_bootup(struct pp_hwmgr *hwmgr) 490 { 491 struct smu8_smumgr *smu8_smu = hwmgr->smu_backend; 492 493 smu8_smu->toc_entry_initialize_index = smu8_smu->toc_entry_used_count; 494 495 smu8_smu_populate_single_ucode_load_task(hwmgr, 496 SMU8_SCRATCH_ENTRY_UCODE_ID_SDMA0, false); 497 if (hwmgr->chip_id != CHIP_STONEY) 498 smu8_smu_populate_single_ucode_load_task(hwmgr, 499 SMU8_SCRATCH_ENTRY_UCODE_ID_SDMA1, false); 500 smu8_smu_populate_single_ucode_load_task(hwmgr, 501 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_CE, false); 502 smu8_smu_populate_single_ucode_load_task(hwmgr, 503 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_PFP, false); 504 smu8_smu_populate_single_ucode_load_task(hwmgr, 505 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_ME, false); 506 smu8_smu_populate_single_ucode_load_task(hwmgr, 507 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, false); 508 if (hwmgr->chip_id != CHIP_STONEY) 509 smu8_smu_populate_single_ucode_load_task(hwmgr, 510 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2, false); 511 smu8_smu_populate_single_ucode_load_task(hwmgr, 512 SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_G, true); 513 514 return 0; 515 } 516 517 static int smu8_smu_construct_toc_for_clock_table(struct pp_hwmgr *hwmgr) 518 { 519 struct smu8_smumgr *smu8_smu = hwmgr->smu_backend; 520 521 smu8_smu->toc_entry_clock_table = smu8_smu->toc_entry_used_count; 522 523 smu8_smu_populate_single_scratch_task(hwmgr, 524 SMU8_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE, 525 TASK_TYPE_INITIALIZE, true); 526 527 return 0; 528 } 529 530 static int smu8_smu_construct_toc(struct pp_hwmgr *hwmgr) 531 { 532 struct smu8_smumgr *smu8_smu = hwmgr->smu_backend; 533 534 smu8_smu->toc_entry_used_count = 0; 535 smu8_smu_initialize_toc_empty_job_list(hwmgr); 536 smu8_smu_construct_toc_for_rlc_aram_save(hwmgr); 537 smu8_smu_construct_toc_for_vddgfx_enter(hwmgr); 538 smu8_smu_construct_toc_for_vddgfx_exit(hwmgr); 539 smu8_smu_construct_toc_for_power_profiling(hwmgr); 540 smu8_smu_construct_toc_for_bootup(hwmgr); 541 smu8_smu_construct_toc_for_clock_table(hwmgr); 542 543 return 0; 544 } 545 546 static int smu8_smu_populate_firmware_entries(struct pp_hwmgr *hwmgr) 547 { 548 struct smu8_smumgr *smu8_smu = hwmgr->smu_backend; 549 uint32_t firmware_type; 550 uint32_t i; 551 int ret; 552 enum cgs_ucode_id ucode_id; 553 struct cgs_firmware_info info = {0}; 554 555 smu8_smu->driver_buffer_length = 0; 556 557 for (i = 0; i < ARRAY_SIZE(firmware_list); i++) { 558 559 firmware_type = smu8_translate_firmware_enum_to_arg(hwmgr, 560 firmware_list[i]); 561 562 ucode_id = smu8_convert_fw_type_to_cgs(firmware_type); 563 564 ret = cgs_get_firmware_info(hwmgr->device, 565 ucode_id, &info); 566 567 if (ret == 0) { 568 smu8_smu->driver_buffer[i].mc_addr = info.mc_addr; 569 570 smu8_smu->driver_buffer[i].data_size = info.image_size; 571 572 smu8_smu->driver_buffer[i].firmware_ID = firmware_list[i]; 573 smu8_smu->driver_buffer_length++; 574 } 575 } 576 577 return 0; 578 } 579 580 static int smu8_smu_populate_single_scratch_entry( 581 struct pp_hwmgr *hwmgr, 582 enum smu8_scratch_entry scratch_type, 583 uint32_t ulsize_byte, 584 struct smu8_buffer_entry *entry) 585 { 586 struct smu8_smumgr *smu8_smu = hwmgr->smu_backend; 587 uint32_t ulsize_aligned = SIZE_ALIGN_32(ulsize_byte); 588 589 entry->data_size = ulsize_byte; 590 entry->kaddr = (char *) smu8_smu->smu_buffer.kaddr + 591 smu8_smu->smu_buffer_used_bytes; 592 entry->mc_addr = smu8_smu->smu_buffer.mc_addr + smu8_smu->smu_buffer_used_bytes; 593 entry->firmware_ID = scratch_type; 594 595 smu8_smu->smu_buffer_used_bytes += ulsize_aligned; 596 597 return 0; 598 } 599 600 static int smu8_download_pptable_settings(struct pp_hwmgr *hwmgr, void **table) 601 { 602 struct smu8_smumgr *smu8_smu = hwmgr->smu_backend; 603 unsigned long i; 604 605 for (i = 0; i < smu8_smu->scratch_buffer_length; i++) { 606 if (smu8_smu->scratch_buffer[i].firmware_ID 607 == SMU8_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE) 608 break; 609 } 610 611 *table = (struct SMU8_Fusion_ClkTable *)smu8_smu->scratch_buffer[i].kaddr; 612 613 smum_send_msg_to_smc_with_parameter(hwmgr, 614 PPSMC_MSG_SetClkTableAddrHi, 615 upper_32_bits(smu8_smu->scratch_buffer[i].mc_addr), 616 NULL); 617 618 smum_send_msg_to_smc_with_parameter(hwmgr, 619 PPSMC_MSG_SetClkTableAddrLo, 620 lower_32_bits(smu8_smu->scratch_buffer[i].mc_addr), 621 NULL); 622 623 smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_ExecuteJob, 624 smu8_smu->toc_entry_clock_table, 625 NULL); 626 627 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ClkTableXferToDram, NULL); 628 629 return 0; 630 } 631 632 static int smu8_upload_pptable_settings(struct pp_hwmgr *hwmgr) 633 { 634 struct smu8_smumgr *smu8_smu = hwmgr->smu_backend; 635 unsigned long i; 636 637 for (i = 0; i < smu8_smu->scratch_buffer_length; i++) { 638 if (smu8_smu->scratch_buffer[i].firmware_ID 639 == SMU8_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE) 640 break; 641 } 642 643 smum_send_msg_to_smc_with_parameter(hwmgr, 644 PPSMC_MSG_SetClkTableAddrHi, 645 upper_32_bits(smu8_smu->scratch_buffer[i].mc_addr), 646 NULL); 647 648 smum_send_msg_to_smc_with_parameter(hwmgr, 649 PPSMC_MSG_SetClkTableAddrLo, 650 lower_32_bits(smu8_smu->scratch_buffer[i].mc_addr), 651 NULL); 652 653 smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_ExecuteJob, 654 smu8_smu->toc_entry_clock_table, 655 NULL); 656 657 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ClkTableXferToSmu, NULL); 658 659 return 0; 660 } 661 662 static int smu8_request_smu_load_fw(struct pp_hwmgr *hwmgr) 663 { 664 struct smu8_smumgr *smu8_smu = hwmgr->smu_backend; 665 uint32_t smc_address; 666 uint32_t fw_to_check = 0; 667 int ret; 668 669 amdgpu_ucode_init_bo(hwmgr->adev); 670 671 smu8_smu_populate_firmware_entries(hwmgr); 672 673 smu8_smu_construct_toc(hwmgr); 674 675 smc_address = SMU8_FIRMWARE_HEADER_LOCATION + 676 offsetof(struct SMU8_Firmware_Header, UcodeLoadStatus); 677 678 smu8_write_smc_sram_dword(hwmgr, smc_address, 0, smc_address+4); 679 680 smum_send_msg_to_smc_with_parameter(hwmgr, 681 PPSMC_MSG_DriverDramAddrHi, 682 upper_32_bits(smu8_smu->toc_buffer.mc_addr), 683 NULL); 684 685 smum_send_msg_to_smc_with_parameter(hwmgr, 686 PPSMC_MSG_DriverDramAddrLo, 687 lower_32_bits(smu8_smu->toc_buffer.mc_addr), 688 NULL); 689 690 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_InitJobs, NULL); 691 692 smum_send_msg_to_smc_with_parameter(hwmgr, 693 PPSMC_MSG_ExecuteJob, 694 smu8_smu->toc_entry_aram, 695 NULL); 696 smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_ExecuteJob, 697 smu8_smu->toc_entry_power_profiling_index, 698 NULL); 699 700 smum_send_msg_to_smc_with_parameter(hwmgr, 701 PPSMC_MSG_ExecuteJob, 702 smu8_smu->toc_entry_initialize_index, 703 NULL); 704 705 fw_to_check = UCODE_ID_RLC_G_MASK | 706 UCODE_ID_SDMA0_MASK | 707 UCODE_ID_SDMA1_MASK | 708 UCODE_ID_CP_CE_MASK | 709 UCODE_ID_CP_ME_MASK | 710 UCODE_ID_CP_PFP_MASK | 711 UCODE_ID_CP_MEC_JT1_MASK | 712 UCODE_ID_CP_MEC_JT2_MASK; 713 714 if (hwmgr->chip_id == CHIP_STONEY) 715 fw_to_check &= ~(UCODE_ID_SDMA1_MASK | UCODE_ID_CP_MEC_JT2_MASK); 716 717 ret = smu8_check_fw_load_finish(hwmgr, fw_to_check); 718 if (ret) { 719 pr_err("SMU firmware load failed\n"); 720 return ret; 721 } 722 723 ret = smu8_load_mec_firmware(hwmgr); 724 if (ret) { 725 pr_err("Mec Firmware load failed\n"); 726 return ret; 727 } 728 729 return 0; 730 } 731 732 static int smu8_start_smu(struct pp_hwmgr *hwmgr) 733 { 734 struct amdgpu_device *adev; 735 736 uint32_t index = SMN_MP1_SRAM_START_ADDR + 737 SMU8_FIRMWARE_HEADER_LOCATION + 738 offsetof(struct SMU8_Firmware_Header, Version); 739 740 if (hwmgr == NULL || hwmgr->device == NULL) 741 return -EINVAL; 742 743 adev = hwmgr->adev; 744 745 cgs_write_register(hwmgr->device, mmMP0PUB_IND_INDEX, index); 746 hwmgr->smu_version = cgs_read_register(hwmgr->device, mmMP0PUB_IND_DATA); 747 pr_info("smu version %02d.%02d.%02d\n", 748 ((hwmgr->smu_version >> 16) & 0xFF), 749 ((hwmgr->smu_version >> 8) & 0xFF), 750 (hwmgr->smu_version & 0xFF)); 751 adev->pm.fw_version = hwmgr->smu_version >> 8; 752 753 return smu8_request_smu_load_fw(hwmgr); 754 } 755 756 static int smu8_smu_init(struct pp_hwmgr *hwmgr) 757 { 758 int ret = 0; 759 struct smu8_smumgr *smu8_smu; 760 761 smu8_smu = kzalloc(sizeof(struct smu8_smumgr), GFP_KERNEL); 762 if (smu8_smu == NULL) 763 return -ENOMEM; 764 765 hwmgr->smu_backend = smu8_smu; 766 767 smu8_smu->toc_buffer.data_size = 4096; 768 smu8_smu->smu_buffer.data_size = 769 ALIGN(UCODE_ID_RLC_SCRATCH_SIZE_BYTE, 32) + 770 ALIGN(UCODE_ID_RLC_SRM_ARAM_SIZE_BYTE, 32) + 771 ALIGN(UCODE_ID_RLC_SRM_DRAM_SIZE_BYTE, 32) + 772 ALIGN(sizeof(struct SMU8_MultimediaPowerLogData), 32) + 773 ALIGN(sizeof(struct SMU8_Fusion_ClkTable), 32); 774 775 ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev, 776 smu8_smu->toc_buffer.data_size, 777 PAGE_SIZE, 778 AMDGPU_GEM_DOMAIN_VRAM, 779 &smu8_smu->toc_buffer.handle, 780 &smu8_smu->toc_buffer.mc_addr, 781 &smu8_smu->toc_buffer.kaddr); 782 if (ret) 783 goto err2; 784 785 ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev, 786 smu8_smu->smu_buffer.data_size, 787 PAGE_SIZE, 788 AMDGPU_GEM_DOMAIN_VRAM, 789 &smu8_smu->smu_buffer.handle, 790 &smu8_smu->smu_buffer.mc_addr, 791 &smu8_smu->smu_buffer.kaddr); 792 if (ret) 793 goto err1; 794 795 if (0 != smu8_smu_populate_single_scratch_entry(hwmgr, 796 SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH, 797 UCODE_ID_RLC_SCRATCH_SIZE_BYTE, 798 &smu8_smu->scratch_buffer[smu8_smu->scratch_buffer_length++])) { 799 pr_err("Error when Populate Firmware Entry.\n"); 800 goto err0; 801 } 802 803 if (0 != smu8_smu_populate_single_scratch_entry(hwmgr, 804 SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM, 805 UCODE_ID_RLC_SRM_ARAM_SIZE_BYTE, 806 &smu8_smu->scratch_buffer[smu8_smu->scratch_buffer_length++])) { 807 pr_err("Error when Populate Firmware Entry.\n"); 808 goto err0; 809 } 810 if (0 != smu8_smu_populate_single_scratch_entry(hwmgr, 811 SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM, 812 UCODE_ID_RLC_SRM_DRAM_SIZE_BYTE, 813 &smu8_smu->scratch_buffer[smu8_smu->scratch_buffer_length++])) { 814 pr_err("Error when Populate Firmware Entry.\n"); 815 goto err0; 816 } 817 818 if (0 != smu8_smu_populate_single_scratch_entry(hwmgr, 819 SMU8_SCRATCH_ENTRY_UCODE_ID_POWER_PROFILING, 820 sizeof(struct SMU8_MultimediaPowerLogData), 821 &smu8_smu->scratch_buffer[smu8_smu->scratch_buffer_length++])) { 822 pr_err("Error when Populate Firmware Entry.\n"); 823 goto err0; 824 } 825 826 if (0 != smu8_smu_populate_single_scratch_entry(hwmgr, 827 SMU8_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE, 828 sizeof(struct SMU8_Fusion_ClkTable), 829 &smu8_smu->scratch_buffer[smu8_smu->scratch_buffer_length++])) { 830 pr_err("Error when Populate Firmware Entry.\n"); 831 goto err0; 832 } 833 834 return 0; 835 836 err0: 837 amdgpu_bo_free_kernel(&smu8_smu->smu_buffer.handle, 838 &smu8_smu->smu_buffer.mc_addr, 839 &smu8_smu->smu_buffer.kaddr); 840 err1: 841 amdgpu_bo_free_kernel(&smu8_smu->toc_buffer.handle, 842 &smu8_smu->toc_buffer.mc_addr, 843 &smu8_smu->toc_buffer.kaddr); 844 err2: 845 kfree(smu8_smu); 846 return -EINVAL; 847 } 848 849 static int smu8_smu_fini(struct pp_hwmgr *hwmgr) 850 { 851 struct smu8_smumgr *smu8_smu; 852 853 if (hwmgr == NULL || hwmgr->device == NULL) 854 return -EINVAL; 855 856 smu8_smu = hwmgr->smu_backend; 857 if (smu8_smu) { 858 amdgpu_bo_free_kernel(&smu8_smu->toc_buffer.handle, 859 &smu8_smu->toc_buffer.mc_addr, 860 &smu8_smu->toc_buffer.kaddr); 861 amdgpu_bo_free_kernel(&smu8_smu->smu_buffer.handle, 862 &smu8_smu->smu_buffer.mc_addr, 863 &smu8_smu->smu_buffer.kaddr); 864 kfree(smu8_smu); 865 } 866 867 return 0; 868 } 869 870 static bool smu8_dpm_check_smu_features(struct pp_hwmgr *hwmgr, 871 unsigned long check_feature) 872 { 873 int result; 874 uint32_t features; 875 876 result = smum_send_msg_to_smc_with_parameter(hwmgr, 877 PPSMC_MSG_GetFeatureStatus, 878 0, 879 &features); 880 if (result == 0) { 881 if (features & check_feature) 882 return true; 883 } 884 885 return false; 886 } 887 888 static bool smu8_is_dpm_running(struct pp_hwmgr *hwmgr) 889 { 890 if (smu8_dpm_check_smu_features(hwmgr, SMU_EnabledFeatureScoreboard_SclkDpmOn)) 891 return true; 892 return false; 893 } 894 895 const struct pp_smumgr_func smu8_smu_funcs = { 896 .name = "smu8_smu", 897 .smu_init = smu8_smu_init, 898 .smu_fini = smu8_smu_fini, 899 .start_smu = smu8_start_smu, 900 .check_fw_load_finish = smu8_check_fw_load_finish, 901 .request_smu_load_fw = NULL, 902 .request_smu_load_specific_fw = NULL, 903 .get_argument = smu8_get_argument, 904 .send_msg_to_smc = smu8_send_msg_to_smc, 905 .send_msg_to_smc_with_parameter = smu8_send_msg_to_smc_with_parameter, 906 .download_pptable_settings = smu8_download_pptable_settings, 907 .upload_pptable_settings = smu8_upload_pptable_settings, 908 .is_dpm_running = smu8_is_dpm_running, 909 }; 910 911