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 #include "pp_debug.h" 24 #include <linux/delay.h> 25 #include <linux/fb.h> 26 #include <linux/module.h> 27 #include <linux/pci.h> 28 #include <linux/slab.h> 29 #include <asm/div64.h> 30 #if IS_ENABLED(CONFIG_X86_64) && defined(__linux__) 31 #include <asm/intel-family.h> 32 #endif 33 #include <drm/amdgpu_drm.h> 34 #include "ppatomctrl.h" 35 #include "atombios.h" 36 #include "pptable_v1_0.h" 37 #include "pppcielanes.h" 38 #include "amd_pcie_helpers.h" 39 #include "hardwaremanager.h" 40 #include "process_pptables_v1_0.h" 41 #include "cgs_common.h" 42 43 #include "smu7_common.h" 44 45 #include "hwmgr.h" 46 #include "smu7_hwmgr.h" 47 #include "smu_ucode_xfer_vi.h" 48 #include "smu7_powertune.h" 49 #include "smu7_dyn_defaults.h" 50 #include "smu7_thermal.h" 51 #include "smu7_clockpowergating.h" 52 #include "processpptables.h" 53 #include "pp_thermal.h" 54 #include "smu7_baco.h" 55 56 #include "ivsrcid/ivsrcid_vislands30.h" 57 58 #define MC_CG_ARB_FREQ_F0 0x0a 59 #define MC_CG_ARB_FREQ_F1 0x0b 60 #define MC_CG_ARB_FREQ_F2 0x0c 61 #define MC_CG_ARB_FREQ_F3 0x0d 62 63 #define MC_CG_SEQ_DRAMCONF_S0 0x05 64 #define MC_CG_SEQ_DRAMCONF_S1 0x06 65 #define MC_CG_SEQ_YCLK_SUSPEND 0x04 66 #define MC_CG_SEQ_YCLK_RESUME 0x0a 67 68 #define SMC_CG_IND_START 0xc0030000 69 #define SMC_CG_IND_END 0xc0040000 70 71 #define MEM_FREQ_LOW_LATENCY 25000 72 #define MEM_FREQ_HIGH_LATENCY 80000 73 74 #define MEM_LATENCY_HIGH 45 75 #define MEM_LATENCY_LOW 35 76 #define MEM_LATENCY_ERR 0xFFFF 77 78 #define MC_SEQ_MISC0_GDDR5_SHIFT 28 79 #define MC_SEQ_MISC0_GDDR5_MASK 0xf0000000 80 #define MC_SEQ_MISC0_GDDR5_VALUE 5 81 82 #define PCIE_BUS_CLK 10000 83 #define TCLK (PCIE_BUS_CLK / 10) 84 85 static struct profile_mode_setting smu7_profiling[7] = 86 {{0, 0, 0, 0, 0, 0, 0, 0}, 87 {1, 0, 100, 30, 1, 0, 100, 10}, 88 {1, 10, 0, 30, 0, 0, 0, 0}, 89 {0, 0, 0, 0, 1, 10, 16, 31}, 90 {1, 0, 11, 50, 1, 0, 100, 10}, 91 {1, 0, 5, 30, 0, 0, 0, 0}, 92 {0, 0, 0, 0, 0, 0, 0, 0}, 93 }; 94 95 #define PPSMC_MSG_SetVBITimeout_VEGAM ((uint16_t) 0x310) 96 97 #define ixPWR_SVI2_PLANE1_LOAD 0xC0200280 98 #define PWR_SVI2_PLANE1_LOAD__PSI1_MASK 0x00000020L 99 #define PWR_SVI2_PLANE1_LOAD__PSI0_EN_MASK 0x00000040L 100 #define PWR_SVI2_PLANE1_LOAD__PSI1__SHIFT 0x00000005 101 #define PWR_SVI2_PLANE1_LOAD__PSI0_EN__SHIFT 0x00000006 102 103 /** Values for the CG_THERMAL_CTRL::DPM_EVENT_SRC field. */ 104 enum DPM_EVENT_SRC { 105 DPM_EVENT_SRC_ANALOG = 0, 106 DPM_EVENT_SRC_EXTERNAL = 1, 107 DPM_EVENT_SRC_DIGITAL = 2, 108 DPM_EVENT_SRC_ANALOG_OR_EXTERNAL = 3, 109 DPM_EVENT_SRC_DIGITAL_OR_EXTERNAL = 4 110 }; 111 112 static const unsigned long PhwVIslands_Magic = (unsigned long)(PHM_VIslands_Magic); 113 static int smu7_force_clock_level(struct pp_hwmgr *hwmgr, 114 enum pp_clock_type type, uint32_t mask); 115 116 static struct smu7_power_state *cast_phw_smu7_power_state( 117 struct pp_hw_power_state *hw_ps) 118 { 119 PP_ASSERT_WITH_CODE((PhwVIslands_Magic == hw_ps->magic), 120 "Invalid Powerstate Type!", 121 return NULL); 122 123 return (struct smu7_power_state *)hw_ps; 124 } 125 126 static const struct smu7_power_state *cast_const_phw_smu7_power_state( 127 const struct pp_hw_power_state *hw_ps) 128 { 129 PP_ASSERT_WITH_CODE((PhwVIslands_Magic == hw_ps->magic), 130 "Invalid Powerstate Type!", 131 return NULL); 132 133 return (const struct smu7_power_state *)hw_ps; 134 } 135 136 /** 137 * Find the MC microcode version and store it in the HwMgr struct 138 * 139 * @param hwmgr the address of the powerplay hardware manager. 140 * @return always 0 141 */ 142 static int smu7_get_mc_microcode_version(struct pp_hwmgr *hwmgr) 143 { 144 cgs_write_register(hwmgr->device, mmMC_SEQ_IO_DEBUG_INDEX, 0x9F); 145 146 hwmgr->microcode_version_info.MC = cgs_read_register(hwmgr->device, mmMC_SEQ_IO_DEBUG_DATA); 147 148 return 0; 149 } 150 151 static uint16_t smu7_get_current_pcie_speed(struct pp_hwmgr *hwmgr) 152 { 153 uint32_t speedCntl = 0; 154 155 /* mmPCIE_PORT_INDEX rename as mmPCIE_INDEX */ 156 speedCntl = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__PCIE, 157 ixPCIE_LC_SPEED_CNTL); 158 return((uint16_t)PHM_GET_FIELD(speedCntl, 159 PCIE_LC_SPEED_CNTL, LC_CURRENT_DATA_RATE)); 160 } 161 162 static int smu7_get_current_pcie_lane_number(struct pp_hwmgr *hwmgr) 163 { 164 uint32_t link_width; 165 166 /* mmPCIE_PORT_INDEX rename as mmPCIE_INDEX */ 167 link_width = PHM_READ_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__PCIE, 168 PCIE_LC_LINK_WIDTH_CNTL, LC_LINK_WIDTH_RD); 169 170 PP_ASSERT_WITH_CODE((7 >= link_width), 171 "Invalid PCIe lane width!", return 0); 172 173 return decode_pcie_lane_width(link_width); 174 } 175 176 /** 177 * Enable voltage control 178 * 179 * @param pHwMgr the address of the powerplay hardware manager. 180 * @return always PP_Result_OK 181 */ 182 static int smu7_enable_smc_voltage_controller(struct pp_hwmgr *hwmgr) 183 { 184 if (hwmgr->chip_id == CHIP_VEGAM) { 185 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, 186 CGS_IND_REG__SMC, PWR_SVI2_PLANE1_LOAD, PSI1, 0); 187 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, 188 CGS_IND_REG__SMC, PWR_SVI2_PLANE1_LOAD, PSI0_EN, 0); 189 } 190 191 if (hwmgr->feature_mask & PP_SMC_VOLTAGE_CONTROL_MASK) 192 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_Voltage_Cntl_Enable, NULL); 193 194 return 0; 195 } 196 197 /** 198 * Checks if we want to support voltage control 199 * 200 * @param hwmgr the address of the powerplay hardware manager. 201 */ 202 static bool smu7_voltage_control(const struct pp_hwmgr *hwmgr) 203 { 204 const struct smu7_hwmgr *data = 205 (const struct smu7_hwmgr *)(hwmgr->backend); 206 207 return (SMU7_VOLTAGE_CONTROL_NONE != data->voltage_control); 208 } 209 210 /** 211 * Enable voltage control 212 * 213 * @param hwmgr the address of the powerplay hardware manager. 214 * @return always 0 215 */ 216 static int smu7_enable_voltage_control(struct pp_hwmgr *hwmgr) 217 { 218 /* enable voltage control */ 219 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, 220 GENERAL_PWRMGT, VOLT_PWRMGT_EN, 1); 221 222 return 0; 223 } 224 225 static int phm_get_svi2_voltage_table_v0(pp_atomctrl_voltage_table *voltage_table, 226 struct phm_clock_voltage_dependency_table *voltage_dependency_table 227 ) 228 { 229 uint32_t i; 230 231 PP_ASSERT_WITH_CODE((NULL != voltage_table), 232 "Voltage Dependency Table empty.", return -EINVAL;); 233 234 voltage_table->mask_low = 0; 235 voltage_table->phase_delay = 0; 236 voltage_table->count = voltage_dependency_table->count; 237 238 for (i = 0; i < voltage_dependency_table->count; i++) { 239 voltage_table->entries[i].value = 240 voltage_dependency_table->entries[i].v; 241 voltage_table->entries[i].smio_low = 0; 242 } 243 244 return 0; 245 } 246 247 248 /** 249 * Create Voltage Tables. 250 * 251 * @param hwmgr the address of the powerplay hardware manager. 252 * @return always 0 253 */ 254 static int smu7_construct_voltage_tables(struct pp_hwmgr *hwmgr) 255 { 256 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 257 struct phm_ppt_v1_information *table_info = 258 (struct phm_ppt_v1_information *)hwmgr->pptable; 259 int result = 0; 260 uint32_t tmp; 261 262 if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) { 263 result = atomctrl_get_voltage_table_v3(hwmgr, 264 VOLTAGE_TYPE_MVDDC, VOLTAGE_OBJ_GPIO_LUT, 265 &(data->mvdd_voltage_table)); 266 PP_ASSERT_WITH_CODE((0 == result), 267 "Failed to retrieve MVDD table.", 268 return result); 269 } else if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->mvdd_control) { 270 if (hwmgr->pp_table_version == PP_TABLE_V1) 271 result = phm_get_svi2_mvdd_voltage_table(&(data->mvdd_voltage_table), 272 table_info->vdd_dep_on_mclk); 273 else if (hwmgr->pp_table_version == PP_TABLE_V0) 274 result = phm_get_svi2_voltage_table_v0(&(data->mvdd_voltage_table), 275 hwmgr->dyn_state.mvdd_dependency_on_mclk); 276 277 PP_ASSERT_WITH_CODE((0 == result), 278 "Failed to retrieve SVI2 MVDD table from dependency table.", 279 return result;); 280 } 281 282 if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) { 283 result = atomctrl_get_voltage_table_v3(hwmgr, 284 VOLTAGE_TYPE_VDDCI, VOLTAGE_OBJ_GPIO_LUT, 285 &(data->vddci_voltage_table)); 286 PP_ASSERT_WITH_CODE((0 == result), 287 "Failed to retrieve VDDCI table.", 288 return result); 289 } else if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) { 290 if (hwmgr->pp_table_version == PP_TABLE_V1) 291 result = phm_get_svi2_vddci_voltage_table(&(data->vddci_voltage_table), 292 table_info->vdd_dep_on_mclk); 293 else if (hwmgr->pp_table_version == PP_TABLE_V0) 294 result = phm_get_svi2_voltage_table_v0(&(data->vddci_voltage_table), 295 hwmgr->dyn_state.vddci_dependency_on_mclk); 296 PP_ASSERT_WITH_CODE((0 == result), 297 "Failed to retrieve SVI2 VDDCI table from dependency table.", 298 return result); 299 } 300 301 if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vdd_gfx_control) { 302 /* VDDGFX has only SVI2 voltage control */ 303 result = phm_get_svi2_vdd_voltage_table(&(data->vddgfx_voltage_table), 304 table_info->vddgfx_lookup_table); 305 PP_ASSERT_WITH_CODE((0 == result), 306 "Failed to retrieve SVI2 VDDGFX table from lookup table.", return result;); 307 } 308 309 310 if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->voltage_control) { 311 result = atomctrl_get_voltage_table_v3(hwmgr, 312 VOLTAGE_TYPE_VDDC, VOLTAGE_OBJ_GPIO_LUT, 313 &data->vddc_voltage_table); 314 PP_ASSERT_WITH_CODE((0 == result), 315 "Failed to retrieve VDDC table.", return result;); 316 } else if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) { 317 318 if (hwmgr->pp_table_version == PP_TABLE_V0) 319 result = phm_get_svi2_voltage_table_v0(&data->vddc_voltage_table, 320 hwmgr->dyn_state.vddc_dependency_on_mclk); 321 else if (hwmgr->pp_table_version == PP_TABLE_V1) 322 result = phm_get_svi2_vdd_voltage_table(&(data->vddc_voltage_table), 323 table_info->vddc_lookup_table); 324 325 PP_ASSERT_WITH_CODE((0 == result), 326 "Failed to retrieve SVI2 VDDC table from dependency table.", return result;); 327 } 328 329 tmp = smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_VDDC); 330 PP_ASSERT_WITH_CODE( 331 (data->vddc_voltage_table.count <= tmp), 332 "Too many voltage values for VDDC. Trimming to fit state table.", 333 phm_trim_voltage_table_to_fit_state_table(tmp, 334 &(data->vddc_voltage_table))); 335 336 tmp = smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_VDDGFX); 337 PP_ASSERT_WITH_CODE( 338 (data->vddgfx_voltage_table.count <= tmp), 339 "Too many voltage values for VDDC. Trimming to fit state table.", 340 phm_trim_voltage_table_to_fit_state_table(tmp, 341 &(data->vddgfx_voltage_table))); 342 343 tmp = smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_VDDCI); 344 PP_ASSERT_WITH_CODE( 345 (data->vddci_voltage_table.count <= tmp), 346 "Too many voltage values for VDDCI. Trimming to fit state table.", 347 phm_trim_voltage_table_to_fit_state_table(tmp, 348 &(data->vddci_voltage_table))); 349 350 tmp = smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_MVDD); 351 PP_ASSERT_WITH_CODE( 352 (data->mvdd_voltage_table.count <= tmp), 353 "Too many voltage values for MVDD. Trimming to fit state table.", 354 phm_trim_voltage_table_to_fit_state_table(tmp, 355 &(data->mvdd_voltage_table))); 356 357 return 0; 358 } 359 360 /** 361 * Programs static screed detection parameters 362 * 363 * @param hwmgr the address of the powerplay hardware manager. 364 * @return always 0 365 */ 366 static int smu7_program_static_screen_threshold_parameters( 367 struct pp_hwmgr *hwmgr) 368 { 369 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 370 371 /* Set static screen threshold unit */ 372 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, 373 CG_STATIC_SCREEN_PARAMETER, STATIC_SCREEN_THRESHOLD_UNIT, 374 data->static_screen_threshold_unit); 375 /* Set static screen threshold */ 376 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, 377 CG_STATIC_SCREEN_PARAMETER, STATIC_SCREEN_THRESHOLD, 378 data->static_screen_threshold); 379 380 return 0; 381 } 382 383 /** 384 * Setup display gap for glitch free memory clock switching. 385 * 386 * @param hwmgr the address of the powerplay hardware manager. 387 * @return always 0 388 */ 389 static int smu7_enable_display_gap(struct pp_hwmgr *hwmgr) 390 { 391 uint32_t display_gap = 392 cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, 393 ixCG_DISPLAY_GAP_CNTL); 394 395 display_gap = PHM_SET_FIELD(display_gap, CG_DISPLAY_GAP_CNTL, 396 DISP_GAP, DISPLAY_GAP_IGNORE); 397 398 display_gap = PHM_SET_FIELD(display_gap, CG_DISPLAY_GAP_CNTL, 399 DISP_GAP_MCHG, DISPLAY_GAP_VBLANK); 400 401 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 402 ixCG_DISPLAY_GAP_CNTL, display_gap); 403 404 return 0; 405 } 406 407 /** 408 * Programs activity state transition voting clients 409 * 410 * @param hwmgr the address of the powerplay hardware manager. 411 * @return always 0 412 */ 413 static int smu7_program_voting_clients(struct pp_hwmgr *hwmgr) 414 { 415 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 416 int i; 417 418 /* Clear reset for voting clients before enabling DPM */ 419 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, 420 SCLK_PWRMGT_CNTL, RESET_SCLK_CNT, 0); 421 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, 422 SCLK_PWRMGT_CNTL, RESET_BUSY_CNT, 0); 423 424 for (i = 0; i < 8; i++) 425 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 426 ixCG_FREQ_TRAN_VOTING_0 + i * 4, 427 data->voting_rights_clients[i]); 428 return 0; 429 } 430 431 static int smu7_clear_voting_clients(struct pp_hwmgr *hwmgr) 432 { 433 int i; 434 435 /* Reset voting clients before disabling DPM */ 436 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, 437 SCLK_PWRMGT_CNTL, RESET_SCLK_CNT, 1); 438 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, 439 SCLK_PWRMGT_CNTL, RESET_BUSY_CNT, 1); 440 441 for (i = 0; i < 8; i++) 442 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 443 ixCG_FREQ_TRAN_VOTING_0 + i * 4, 0); 444 445 return 0; 446 } 447 448 /* Copy one arb setting to another and then switch the active set. 449 * arb_src and arb_dest is one of the MC_CG_ARB_FREQ_Fx constants. 450 */ 451 static int smu7_copy_and_switch_arb_sets(struct pp_hwmgr *hwmgr, 452 uint32_t arb_src, uint32_t arb_dest) 453 { 454 uint32_t mc_arb_dram_timing; 455 uint32_t mc_arb_dram_timing2; 456 uint32_t burst_time; 457 uint32_t mc_cg_config; 458 459 switch (arb_src) { 460 case MC_CG_ARB_FREQ_F0: 461 mc_arb_dram_timing = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING); 462 mc_arb_dram_timing2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2); 463 burst_time = PHM_READ_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE0); 464 break; 465 case MC_CG_ARB_FREQ_F1: 466 mc_arb_dram_timing = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING_1); 467 mc_arb_dram_timing2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2_1); 468 burst_time = PHM_READ_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE1); 469 break; 470 default: 471 return -EINVAL; 472 } 473 474 switch (arb_dest) { 475 case MC_CG_ARB_FREQ_F0: 476 cgs_write_register(hwmgr->device, mmMC_ARB_DRAM_TIMING, mc_arb_dram_timing); 477 cgs_write_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2, mc_arb_dram_timing2); 478 PHM_WRITE_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE0, burst_time); 479 break; 480 case MC_CG_ARB_FREQ_F1: 481 cgs_write_register(hwmgr->device, mmMC_ARB_DRAM_TIMING_1, mc_arb_dram_timing); 482 cgs_write_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2_1, mc_arb_dram_timing2); 483 PHM_WRITE_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE1, burst_time); 484 break; 485 default: 486 return -EINVAL; 487 } 488 489 mc_cg_config = cgs_read_register(hwmgr->device, mmMC_CG_CONFIG); 490 mc_cg_config |= 0x0000000F; 491 cgs_write_register(hwmgr->device, mmMC_CG_CONFIG, mc_cg_config); 492 PHM_WRITE_FIELD(hwmgr->device, MC_ARB_CG, CG_ARB_REQ, arb_dest); 493 494 return 0; 495 } 496 497 static int smu7_reset_to_default(struct pp_hwmgr *hwmgr) 498 { 499 return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ResetToDefaults, NULL); 500 } 501 502 /** 503 * Initial switch from ARB F0->F1 504 * 505 * @param hwmgr the address of the powerplay hardware manager. 506 * @return always 0 507 * This function is to be called from the SetPowerState table. 508 */ 509 static int smu7_initial_switch_from_arbf0_to_f1(struct pp_hwmgr *hwmgr) 510 { 511 return smu7_copy_and_switch_arb_sets(hwmgr, 512 MC_CG_ARB_FREQ_F0, MC_CG_ARB_FREQ_F1); 513 } 514 515 static int smu7_force_switch_to_arbf0(struct pp_hwmgr *hwmgr) 516 { 517 uint32_t tmp; 518 519 tmp = (cgs_read_ind_register(hwmgr->device, 520 CGS_IND_REG__SMC, ixSMC_SCRATCH9) & 521 0x0000ff00) >> 8; 522 523 if (tmp == MC_CG_ARB_FREQ_F0) 524 return 0; 525 526 return smu7_copy_and_switch_arb_sets(hwmgr, 527 tmp, MC_CG_ARB_FREQ_F0); 528 } 529 530 static uint16_t smu7_override_pcie_speed(struct pp_hwmgr *hwmgr) 531 { 532 struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev); 533 uint16_t pcie_gen = 0; 534 535 if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN4 && 536 adev->pm.pcie_gen_mask & CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN4) 537 pcie_gen = 3; 538 else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3 && 539 adev->pm.pcie_gen_mask & CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN3) 540 pcie_gen = 2; 541 else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2 && 542 adev->pm.pcie_gen_mask & CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN2) 543 pcie_gen = 1; 544 else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1 && 545 adev->pm.pcie_gen_mask & CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN1) 546 pcie_gen = 0; 547 548 return pcie_gen; 549 } 550 551 static uint16_t smu7_override_pcie_width(struct pp_hwmgr *hwmgr) 552 { 553 struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev); 554 uint16_t pcie_width = 0; 555 556 if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X16) 557 pcie_width = 16; 558 else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X12) 559 pcie_width = 12; 560 else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X8) 561 pcie_width = 8; 562 else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X4) 563 pcie_width = 4; 564 else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X2) 565 pcie_width = 2; 566 else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X1) 567 pcie_width = 1; 568 569 return pcie_width; 570 } 571 572 static int smu7_setup_default_pcie_table(struct pp_hwmgr *hwmgr) 573 { 574 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 575 576 struct phm_ppt_v1_information *table_info = 577 (struct phm_ppt_v1_information *)(hwmgr->pptable); 578 struct phm_ppt_v1_pcie_table *pcie_table = NULL; 579 580 uint32_t i, max_entry; 581 uint32_t tmp; 582 583 PP_ASSERT_WITH_CODE((data->use_pcie_performance_levels || 584 data->use_pcie_power_saving_levels), "No pcie performance levels!", 585 return -EINVAL); 586 587 if (table_info != NULL) 588 pcie_table = table_info->pcie_table; 589 590 if (data->use_pcie_performance_levels && 591 !data->use_pcie_power_saving_levels) { 592 data->pcie_gen_power_saving = data->pcie_gen_performance; 593 data->pcie_lane_power_saving = data->pcie_lane_performance; 594 } else if (!data->use_pcie_performance_levels && 595 data->use_pcie_power_saving_levels) { 596 data->pcie_gen_performance = data->pcie_gen_power_saving; 597 data->pcie_lane_performance = data->pcie_lane_power_saving; 598 } 599 tmp = smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_LINK); 600 phm_reset_single_dpm_table(&data->dpm_table.pcie_speed_table, 601 tmp, 602 MAX_REGULAR_DPM_NUMBER); 603 604 if (pcie_table != NULL) { 605 /* max_entry is used to make sure we reserve one PCIE level 606 * for boot level (fix for A+A PSPP issue). 607 * If PCIE table from PPTable have ULV entry + 8 entries, 608 * then ignore the last entry.*/ 609 max_entry = (tmp < pcie_table->count) ? tmp : pcie_table->count; 610 for (i = 1; i < max_entry; i++) { 611 phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, i - 1, 612 get_pcie_gen_support(data->pcie_gen_cap, 613 pcie_table->entries[i].gen_speed), 614 get_pcie_lane_support(data->pcie_lane_cap, 615 pcie_table->entries[i].lane_width)); 616 } 617 data->dpm_table.pcie_speed_table.count = max_entry - 1; 618 smum_update_smc_table(hwmgr, SMU_BIF_TABLE); 619 } else { 620 /* Hardcode Pcie Table */ 621 phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 0, 622 get_pcie_gen_support(data->pcie_gen_cap, 623 PP_Min_PCIEGen), 624 get_pcie_lane_support(data->pcie_lane_cap, 625 PP_Max_PCIELane)); 626 phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 1, 627 get_pcie_gen_support(data->pcie_gen_cap, 628 PP_Min_PCIEGen), 629 get_pcie_lane_support(data->pcie_lane_cap, 630 PP_Max_PCIELane)); 631 phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 2, 632 get_pcie_gen_support(data->pcie_gen_cap, 633 PP_Max_PCIEGen), 634 get_pcie_lane_support(data->pcie_lane_cap, 635 PP_Max_PCIELane)); 636 phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 3, 637 get_pcie_gen_support(data->pcie_gen_cap, 638 PP_Max_PCIEGen), 639 get_pcie_lane_support(data->pcie_lane_cap, 640 PP_Max_PCIELane)); 641 phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 4, 642 get_pcie_gen_support(data->pcie_gen_cap, 643 PP_Max_PCIEGen), 644 get_pcie_lane_support(data->pcie_lane_cap, 645 PP_Max_PCIELane)); 646 phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 5, 647 get_pcie_gen_support(data->pcie_gen_cap, 648 PP_Max_PCIEGen), 649 get_pcie_lane_support(data->pcie_lane_cap, 650 PP_Max_PCIELane)); 651 652 data->dpm_table.pcie_speed_table.count = 6; 653 } 654 /* Populate last level for boot PCIE level, but do not increment count. */ 655 if (hwmgr->chip_family == AMDGPU_FAMILY_CI) { 656 for (i = 0; i <= data->dpm_table.pcie_speed_table.count; i++) 657 phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, i, 658 get_pcie_gen_support(data->pcie_gen_cap, 659 PP_Max_PCIEGen), 660 data->vbios_boot_state.pcie_lane_bootup_value); 661 } else { 662 phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 663 data->dpm_table.pcie_speed_table.count, 664 get_pcie_gen_support(data->pcie_gen_cap, 665 PP_Min_PCIEGen), 666 get_pcie_lane_support(data->pcie_lane_cap, 667 PP_Max_PCIELane)); 668 669 if (data->pcie_dpm_key_disabled) 670 phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 671 data->dpm_table.pcie_speed_table.count, 672 smu7_override_pcie_speed(hwmgr), smu7_override_pcie_width(hwmgr)); 673 } 674 return 0; 675 } 676 677 static int smu7_reset_dpm_tables(struct pp_hwmgr *hwmgr) 678 { 679 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 680 681 memset(&(data->dpm_table), 0x00, sizeof(data->dpm_table)); 682 683 phm_reset_single_dpm_table( 684 &data->dpm_table.sclk_table, 685 smum_get_mac_definition(hwmgr, 686 SMU_MAX_LEVELS_GRAPHICS), 687 MAX_REGULAR_DPM_NUMBER); 688 phm_reset_single_dpm_table( 689 &data->dpm_table.mclk_table, 690 smum_get_mac_definition(hwmgr, 691 SMU_MAX_LEVELS_MEMORY), MAX_REGULAR_DPM_NUMBER); 692 693 phm_reset_single_dpm_table( 694 &data->dpm_table.vddc_table, 695 smum_get_mac_definition(hwmgr, 696 SMU_MAX_LEVELS_VDDC), 697 MAX_REGULAR_DPM_NUMBER); 698 phm_reset_single_dpm_table( 699 &data->dpm_table.vddci_table, 700 smum_get_mac_definition(hwmgr, 701 SMU_MAX_LEVELS_VDDCI), MAX_REGULAR_DPM_NUMBER); 702 703 phm_reset_single_dpm_table( 704 &data->dpm_table.mvdd_table, 705 smum_get_mac_definition(hwmgr, 706 SMU_MAX_LEVELS_MVDD), 707 MAX_REGULAR_DPM_NUMBER); 708 return 0; 709 } 710 /* 711 * This function is to initialize all DPM state tables 712 * for SMU7 based on the dependency table. 713 * Dynamic state patching function will then trim these 714 * state tables to the allowed range based 715 * on the power policy or external client requests, 716 * such as UVD request, etc. 717 */ 718 719 static int smu7_setup_dpm_tables_v0(struct pp_hwmgr *hwmgr) 720 { 721 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 722 struct phm_clock_voltage_dependency_table *allowed_vdd_sclk_table = 723 hwmgr->dyn_state.vddc_dependency_on_sclk; 724 struct phm_clock_voltage_dependency_table *allowed_vdd_mclk_table = 725 hwmgr->dyn_state.vddc_dependency_on_mclk; 726 struct phm_cac_leakage_table *std_voltage_table = 727 hwmgr->dyn_state.cac_leakage_table; 728 uint32_t i; 729 730 PP_ASSERT_WITH_CODE(allowed_vdd_sclk_table != NULL, 731 "SCLK dependency table is missing. This table is mandatory", return -EINVAL); 732 PP_ASSERT_WITH_CODE(allowed_vdd_sclk_table->count >= 1, 733 "SCLK dependency table has to have is missing. This table is mandatory", return -EINVAL); 734 735 PP_ASSERT_WITH_CODE(allowed_vdd_mclk_table != NULL, 736 "MCLK dependency table is missing. This table is mandatory", return -EINVAL); 737 PP_ASSERT_WITH_CODE(allowed_vdd_mclk_table->count >= 1, 738 "VMCLK dependency table has to have is missing. This table is mandatory", return -EINVAL); 739 740 741 /* Initialize Sclk DPM table based on allow Sclk values*/ 742 data->dpm_table.sclk_table.count = 0; 743 744 for (i = 0; i < allowed_vdd_sclk_table->count; i++) { 745 if (i == 0 || data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count-1].value != 746 allowed_vdd_sclk_table->entries[i].clk) { 747 data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count].value = 748 allowed_vdd_sclk_table->entries[i].clk; 749 data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count].enabled = (i == 0) ? 1 : 0; 750 data->dpm_table.sclk_table.count++; 751 } 752 } 753 754 PP_ASSERT_WITH_CODE(allowed_vdd_mclk_table != NULL, 755 "MCLK dependency table is missing. This table is mandatory", return -EINVAL); 756 /* Initialize Mclk DPM table based on allow Mclk values */ 757 data->dpm_table.mclk_table.count = 0; 758 for (i = 0; i < allowed_vdd_mclk_table->count; i++) { 759 if (i == 0 || data->dpm_table.mclk_table.dpm_levels[data->dpm_table.mclk_table.count-1].value != 760 allowed_vdd_mclk_table->entries[i].clk) { 761 data->dpm_table.mclk_table.dpm_levels[data->dpm_table.mclk_table.count].value = 762 allowed_vdd_mclk_table->entries[i].clk; 763 data->dpm_table.mclk_table.dpm_levels[data->dpm_table.mclk_table.count].enabled = (i == 0) ? 1 : 0; 764 data->dpm_table.mclk_table.count++; 765 } 766 } 767 768 /* Initialize Vddc DPM table based on allow Vddc values. And populate corresponding std values. */ 769 for (i = 0; i < allowed_vdd_sclk_table->count; i++) { 770 data->dpm_table.vddc_table.dpm_levels[i].value = allowed_vdd_mclk_table->entries[i].v; 771 data->dpm_table.vddc_table.dpm_levels[i].param1 = std_voltage_table->entries[i].Leakage; 772 /* param1 is for corresponding std voltage */ 773 data->dpm_table.vddc_table.dpm_levels[i].enabled = true; 774 } 775 776 data->dpm_table.vddc_table.count = allowed_vdd_sclk_table->count; 777 allowed_vdd_mclk_table = hwmgr->dyn_state.vddci_dependency_on_mclk; 778 779 if (NULL != allowed_vdd_mclk_table) { 780 /* Initialize Vddci DPM table based on allow Mclk values */ 781 for (i = 0; i < allowed_vdd_mclk_table->count; i++) { 782 data->dpm_table.vddci_table.dpm_levels[i].value = allowed_vdd_mclk_table->entries[i].v; 783 data->dpm_table.vddci_table.dpm_levels[i].enabled = true; 784 } 785 data->dpm_table.vddci_table.count = allowed_vdd_mclk_table->count; 786 } 787 788 allowed_vdd_mclk_table = hwmgr->dyn_state.mvdd_dependency_on_mclk; 789 790 if (NULL != allowed_vdd_mclk_table) { 791 /* 792 * Initialize MVDD DPM table based on allow Mclk 793 * values 794 */ 795 for (i = 0; i < allowed_vdd_mclk_table->count; i++) { 796 data->dpm_table.mvdd_table.dpm_levels[i].value = allowed_vdd_mclk_table->entries[i].v; 797 data->dpm_table.mvdd_table.dpm_levels[i].enabled = true; 798 } 799 data->dpm_table.mvdd_table.count = allowed_vdd_mclk_table->count; 800 } 801 802 return 0; 803 } 804 805 static int smu7_setup_dpm_tables_v1(struct pp_hwmgr *hwmgr) 806 { 807 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 808 struct phm_ppt_v1_information *table_info = 809 (struct phm_ppt_v1_information *)(hwmgr->pptable); 810 uint32_t i; 811 812 struct phm_ppt_v1_clock_voltage_dependency_table *dep_sclk_table; 813 struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table; 814 815 if (table_info == NULL) 816 return -EINVAL; 817 818 dep_sclk_table = table_info->vdd_dep_on_sclk; 819 dep_mclk_table = table_info->vdd_dep_on_mclk; 820 821 PP_ASSERT_WITH_CODE(dep_sclk_table != NULL, 822 "SCLK dependency table is missing.", 823 return -EINVAL); 824 PP_ASSERT_WITH_CODE(dep_sclk_table->count >= 1, 825 "SCLK dependency table count is 0.", 826 return -EINVAL); 827 828 PP_ASSERT_WITH_CODE(dep_mclk_table != NULL, 829 "MCLK dependency table is missing.", 830 return -EINVAL); 831 PP_ASSERT_WITH_CODE(dep_mclk_table->count >= 1, 832 "MCLK dependency table count is 0", 833 return -EINVAL); 834 835 /* Initialize Sclk DPM table based on allow Sclk values */ 836 data->dpm_table.sclk_table.count = 0; 837 for (i = 0; i < dep_sclk_table->count; i++) { 838 if (i == 0 || data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count - 1].value != 839 dep_sclk_table->entries[i].clk) { 840 841 data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count].value = 842 dep_sclk_table->entries[i].clk; 843 844 data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count].enabled = 845 (i == 0) ? true : false; 846 data->dpm_table.sclk_table.count++; 847 } 848 } 849 if (hwmgr->platform_descriptor.overdriveLimit.engineClock == 0) 850 hwmgr->platform_descriptor.overdriveLimit.engineClock = dep_sclk_table->entries[i-1].clk; 851 /* Initialize Mclk DPM table based on allow Mclk values */ 852 data->dpm_table.mclk_table.count = 0; 853 for (i = 0; i < dep_mclk_table->count; i++) { 854 if (i == 0 || data->dpm_table.mclk_table.dpm_levels 855 [data->dpm_table.mclk_table.count - 1].value != 856 dep_mclk_table->entries[i].clk) { 857 data->dpm_table.mclk_table.dpm_levels[data->dpm_table.mclk_table.count].value = 858 dep_mclk_table->entries[i].clk; 859 data->dpm_table.mclk_table.dpm_levels[data->dpm_table.mclk_table.count].enabled = 860 (i == 0) ? true : false; 861 data->dpm_table.mclk_table.count++; 862 } 863 } 864 865 if (hwmgr->platform_descriptor.overdriveLimit.memoryClock == 0) 866 hwmgr->platform_descriptor.overdriveLimit.memoryClock = dep_mclk_table->entries[i-1].clk; 867 return 0; 868 } 869 870 static int smu7_odn_initial_default_setting(struct pp_hwmgr *hwmgr) 871 { 872 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 873 struct smu7_odn_dpm_table *odn_table = &(data->odn_dpm_table); 874 struct phm_ppt_v1_information *table_info = 875 (struct phm_ppt_v1_information *)(hwmgr->pptable); 876 uint32_t i; 877 878 struct phm_ppt_v1_clock_voltage_dependency_table *dep_sclk_table; 879 struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table; 880 struct phm_odn_performance_level *entries; 881 882 if (table_info == NULL) 883 return -EINVAL; 884 885 dep_sclk_table = table_info->vdd_dep_on_sclk; 886 dep_mclk_table = table_info->vdd_dep_on_mclk; 887 888 odn_table->odn_core_clock_dpm_levels.num_of_pl = 889 data->golden_dpm_table.sclk_table.count; 890 entries = odn_table->odn_core_clock_dpm_levels.entries; 891 for (i=0; i<data->golden_dpm_table.sclk_table.count; i++) { 892 entries[i].clock = data->golden_dpm_table.sclk_table.dpm_levels[i].value; 893 entries[i].enabled = true; 894 entries[i].vddc = dep_sclk_table->entries[i].vddc; 895 } 896 897 smu_get_voltage_dependency_table_ppt_v1(dep_sclk_table, 898 (struct phm_ppt_v1_clock_voltage_dependency_table *)&(odn_table->vdd_dependency_on_sclk)); 899 900 odn_table->odn_memory_clock_dpm_levels.num_of_pl = 901 data->golden_dpm_table.mclk_table.count; 902 entries = odn_table->odn_memory_clock_dpm_levels.entries; 903 for (i=0; i<data->golden_dpm_table.mclk_table.count; i++) { 904 entries[i].clock = data->golden_dpm_table.mclk_table.dpm_levels[i].value; 905 entries[i].enabled = true; 906 entries[i].vddc = dep_mclk_table->entries[i].vddc; 907 } 908 909 smu_get_voltage_dependency_table_ppt_v1(dep_mclk_table, 910 (struct phm_ppt_v1_clock_voltage_dependency_table *)&(odn_table->vdd_dependency_on_mclk)); 911 912 return 0; 913 } 914 915 static void smu7_setup_voltage_range_from_vbios(struct pp_hwmgr *hwmgr) 916 { 917 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 918 struct phm_ppt_v1_clock_voltage_dependency_table *dep_sclk_table; 919 struct phm_ppt_v1_information *table_info = 920 (struct phm_ppt_v1_information *)(hwmgr->pptable); 921 uint32_t min_vddc = 0; 922 uint32_t max_vddc = 0; 923 924 if (!table_info) 925 return; 926 927 dep_sclk_table = table_info->vdd_dep_on_sclk; 928 929 atomctrl_get_voltage_range(hwmgr, &max_vddc, &min_vddc); 930 931 if (min_vddc == 0 || min_vddc > 2000 932 || min_vddc > dep_sclk_table->entries[0].vddc) 933 min_vddc = dep_sclk_table->entries[0].vddc; 934 935 if (max_vddc == 0 || max_vddc > 2000 936 || max_vddc < dep_sclk_table->entries[dep_sclk_table->count-1].vddc) 937 max_vddc = dep_sclk_table->entries[dep_sclk_table->count-1].vddc; 938 939 data->odn_dpm_table.min_vddc = min_vddc; 940 data->odn_dpm_table.max_vddc = max_vddc; 941 } 942 943 static void smu7_check_dpm_table_updated(struct pp_hwmgr *hwmgr) 944 { 945 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 946 struct smu7_odn_dpm_table *odn_table = &(data->odn_dpm_table); 947 struct phm_ppt_v1_information *table_info = 948 (struct phm_ppt_v1_information *)(hwmgr->pptable); 949 uint32_t i; 950 951 struct phm_ppt_v1_clock_voltage_dependency_table *dep_table; 952 struct phm_ppt_v1_clock_voltage_dependency_table *odn_dep_table; 953 954 if (table_info == NULL) 955 return; 956 957 for (i = 0; i < data->dpm_table.sclk_table.count; i++) { 958 if (odn_table->odn_core_clock_dpm_levels.entries[i].clock != 959 data->dpm_table.sclk_table.dpm_levels[i].value) { 960 data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_SCLK; 961 break; 962 } 963 } 964 965 for (i = 0; i < data->dpm_table.mclk_table.count; i++) { 966 if (odn_table->odn_memory_clock_dpm_levels.entries[i].clock != 967 data->dpm_table.mclk_table.dpm_levels[i].value) { 968 data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_MCLK; 969 break; 970 } 971 } 972 973 dep_table = table_info->vdd_dep_on_mclk; 974 odn_dep_table = (struct phm_ppt_v1_clock_voltage_dependency_table *)&(odn_table->vdd_dependency_on_mclk); 975 976 for (i = 0; i < dep_table->count; i++) { 977 if (dep_table->entries[i].vddc != odn_dep_table->entries[i].vddc) { 978 data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_VDDC | DPMTABLE_OD_UPDATE_MCLK; 979 return; 980 } 981 } 982 983 dep_table = table_info->vdd_dep_on_sclk; 984 odn_dep_table = (struct phm_ppt_v1_clock_voltage_dependency_table *)&(odn_table->vdd_dependency_on_sclk); 985 for (i = 0; i < dep_table->count; i++) { 986 if (dep_table->entries[i].vddc != odn_dep_table->entries[i].vddc) { 987 data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_VDDC | DPMTABLE_OD_UPDATE_SCLK; 988 return; 989 } 990 } 991 if (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_VDDC) { 992 data->need_update_smu7_dpm_table &= ~DPMTABLE_OD_UPDATE_VDDC; 993 data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_SCLK | DPMTABLE_OD_UPDATE_MCLK; 994 } 995 } 996 997 static int smu7_setup_default_dpm_tables(struct pp_hwmgr *hwmgr) 998 { 999 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 1000 1001 smu7_reset_dpm_tables(hwmgr); 1002 1003 if (hwmgr->pp_table_version == PP_TABLE_V1) 1004 smu7_setup_dpm_tables_v1(hwmgr); 1005 else if (hwmgr->pp_table_version == PP_TABLE_V0) 1006 smu7_setup_dpm_tables_v0(hwmgr); 1007 1008 smu7_setup_default_pcie_table(hwmgr); 1009 1010 /* save a copy of the default DPM table */ 1011 memcpy(&(data->golden_dpm_table), &(data->dpm_table), 1012 sizeof(struct smu7_dpm_table)); 1013 1014 /* initialize ODN table */ 1015 if (hwmgr->od_enabled) { 1016 if (data->odn_dpm_table.max_vddc) { 1017 smu7_check_dpm_table_updated(hwmgr); 1018 } else { 1019 smu7_setup_voltage_range_from_vbios(hwmgr); 1020 smu7_odn_initial_default_setting(hwmgr); 1021 } 1022 } 1023 return 0; 1024 } 1025 1026 static int smu7_enable_vrhot_gpio_interrupt(struct pp_hwmgr *hwmgr) 1027 { 1028 1029 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, 1030 PHM_PlatformCaps_RegulatorHot)) 1031 return smum_send_msg_to_smc(hwmgr, 1032 PPSMC_MSG_EnableVRHotGPIOInterrupt, 1033 NULL); 1034 1035 return 0; 1036 } 1037 1038 static int smu7_enable_sclk_control(struct pp_hwmgr *hwmgr) 1039 { 1040 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SCLK_PWRMGT_CNTL, 1041 SCLK_PWRMGT_OFF, 0); 1042 return 0; 1043 } 1044 1045 static int smu7_enable_ulv(struct pp_hwmgr *hwmgr) 1046 { 1047 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 1048 1049 if (data->ulv_supported) 1050 return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_EnableULV, NULL); 1051 1052 return 0; 1053 } 1054 1055 static int smu7_disable_ulv(struct pp_hwmgr *hwmgr) 1056 { 1057 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 1058 1059 if (data->ulv_supported) 1060 return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_DisableULV, NULL); 1061 1062 return 0; 1063 } 1064 1065 static int smu7_enable_deep_sleep_master_switch(struct pp_hwmgr *hwmgr) 1066 { 1067 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, 1068 PHM_PlatformCaps_SclkDeepSleep)) { 1069 if (smum_send_msg_to_smc(hwmgr, PPSMC_MSG_MASTER_DeepSleep_ON, NULL)) 1070 PP_ASSERT_WITH_CODE(false, 1071 "Attempt to enable Master Deep Sleep switch failed!", 1072 return -EINVAL); 1073 } else { 1074 if (smum_send_msg_to_smc(hwmgr, 1075 PPSMC_MSG_MASTER_DeepSleep_OFF, 1076 NULL)) { 1077 PP_ASSERT_WITH_CODE(false, 1078 "Attempt to disable Master Deep Sleep switch failed!", 1079 return -EINVAL); 1080 } 1081 } 1082 1083 return 0; 1084 } 1085 1086 static int smu7_disable_deep_sleep_master_switch(struct pp_hwmgr *hwmgr) 1087 { 1088 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, 1089 PHM_PlatformCaps_SclkDeepSleep)) { 1090 if (smum_send_msg_to_smc(hwmgr, 1091 PPSMC_MSG_MASTER_DeepSleep_OFF, 1092 NULL)) { 1093 PP_ASSERT_WITH_CODE(false, 1094 "Attempt to disable Master Deep Sleep switch failed!", 1095 return -EINVAL); 1096 } 1097 } 1098 1099 return 0; 1100 } 1101 1102 static int smu7_disable_sclk_vce_handshake(struct pp_hwmgr *hwmgr) 1103 { 1104 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 1105 uint32_t soft_register_value = 0; 1106 uint32_t handshake_disables_offset = data->soft_regs_start 1107 + smum_get_offsetof(hwmgr, 1108 SMU_SoftRegisters, HandshakeDisables); 1109 1110 soft_register_value = cgs_read_ind_register(hwmgr->device, 1111 CGS_IND_REG__SMC, handshake_disables_offset); 1112 soft_register_value |= SMU7_VCE_SCLK_HANDSHAKE_DISABLE; 1113 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 1114 handshake_disables_offset, soft_register_value); 1115 return 0; 1116 } 1117 1118 static int smu7_disable_handshake_uvd(struct pp_hwmgr *hwmgr) 1119 { 1120 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 1121 uint32_t soft_register_value = 0; 1122 uint32_t handshake_disables_offset = data->soft_regs_start 1123 + smum_get_offsetof(hwmgr, 1124 SMU_SoftRegisters, HandshakeDisables); 1125 1126 soft_register_value = cgs_read_ind_register(hwmgr->device, 1127 CGS_IND_REG__SMC, handshake_disables_offset); 1128 soft_register_value |= smum_get_mac_definition(hwmgr, 1129 SMU_UVD_MCLK_HANDSHAKE_DISABLE); 1130 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 1131 handshake_disables_offset, soft_register_value); 1132 return 0; 1133 } 1134 1135 static int smu7_enable_sclk_mclk_dpm(struct pp_hwmgr *hwmgr) 1136 { 1137 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 1138 1139 /* enable SCLK dpm */ 1140 if (!data->sclk_dpm_key_disabled) { 1141 if (hwmgr->chip_id == CHIP_VEGAM) 1142 smu7_disable_sclk_vce_handshake(hwmgr); 1143 1144 PP_ASSERT_WITH_CODE( 1145 (0 == smum_send_msg_to_smc(hwmgr, PPSMC_MSG_DPM_Enable, NULL)), 1146 "Failed to enable SCLK DPM during DPM Start Function!", 1147 return -EINVAL); 1148 } 1149 1150 /* enable MCLK dpm */ 1151 if (0 == data->mclk_dpm_key_disabled) { 1152 if (!(hwmgr->feature_mask & PP_UVD_HANDSHAKE_MASK)) 1153 smu7_disable_handshake_uvd(hwmgr); 1154 1155 PP_ASSERT_WITH_CODE( 1156 (0 == smum_send_msg_to_smc(hwmgr, 1157 PPSMC_MSG_MCLKDPM_Enable, 1158 NULL)), 1159 "Failed to enable MCLK DPM during DPM Start Function!", 1160 return -EINVAL); 1161 1162 if (hwmgr->chip_family != CHIP_VEGAM) 1163 PHM_WRITE_FIELD(hwmgr->device, MC_SEQ_CNTL_3, CAC_EN, 0x1); 1164 1165 1166 if (hwmgr->chip_family == AMDGPU_FAMILY_CI) { 1167 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 0xc0400d30, 0x5); 1168 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 0xc0400d3c, 0x5); 1169 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 0xc0400d80, 0x100005); 1170 udelay(10); 1171 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 0xc0400d30, 0x400005); 1172 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 0xc0400d3c, 0x400005); 1173 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 0xc0400d80, 0x500005); 1174 } else { 1175 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_MC0_CNTL, 0x5); 1176 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_MC1_CNTL, 0x5); 1177 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_CPL_CNTL, 0x100005); 1178 udelay(10); 1179 if (hwmgr->chip_id == CHIP_VEGAM) { 1180 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_MC0_CNTL, 0x400009); 1181 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_MC1_CNTL, 0x400009); 1182 } else { 1183 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_MC0_CNTL, 0x400005); 1184 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_MC1_CNTL, 0x400005); 1185 } 1186 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_CPL_CNTL, 0x500005); 1187 } 1188 } 1189 1190 return 0; 1191 } 1192 1193 static int smu7_start_dpm(struct pp_hwmgr *hwmgr) 1194 { 1195 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 1196 1197 /*enable general power management */ 1198 1199 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, GENERAL_PWRMGT, 1200 GLOBAL_PWRMGT_EN, 1); 1201 1202 /* enable sclk deep sleep */ 1203 1204 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SCLK_PWRMGT_CNTL, 1205 DYNAMIC_PM_EN, 1); 1206 1207 /* prepare for PCIE DPM */ 1208 1209 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 1210 data->soft_regs_start + 1211 smum_get_offsetof(hwmgr, SMU_SoftRegisters, 1212 VoltageChangeTimeout), 0x1000); 1213 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__PCIE, 1214 SWRST_COMMAND_1, RESETLC, 0x0); 1215 1216 if (hwmgr->chip_family == AMDGPU_FAMILY_CI) 1217 cgs_write_register(hwmgr->device, 0x1488, 1218 (cgs_read_register(hwmgr->device, 0x1488) & ~0x1)); 1219 1220 if (smu7_enable_sclk_mclk_dpm(hwmgr)) { 1221 pr_err("Failed to enable Sclk DPM and Mclk DPM!"); 1222 return -EINVAL; 1223 } 1224 1225 /* enable PCIE dpm */ 1226 if (0 == data->pcie_dpm_key_disabled) { 1227 PP_ASSERT_WITH_CODE( 1228 (0 == smum_send_msg_to_smc(hwmgr, 1229 PPSMC_MSG_PCIeDPM_Enable, 1230 NULL)), 1231 "Failed to enable pcie DPM during DPM Start Function!", 1232 return -EINVAL); 1233 } else { 1234 PP_ASSERT_WITH_CODE( 1235 (0 == smum_send_msg_to_smc(hwmgr, 1236 PPSMC_MSG_PCIeDPM_Disable, 1237 NULL)), 1238 "Failed to disble pcie DPM during DPM Start Function!", 1239 return -EINVAL); 1240 } 1241 1242 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, 1243 PHM_PlatformCaps_Falcon_QuickTransition)) { 1244 PP_ASSERT_WITH_CODE((0 == smum_send_msg_to_smc(hwmgr, 1245 PPSMC_MSG_EnableACDCGPIOInterrupt, 1246 NULL)), 1247 "Failed to enable AC DC GPIO Interrupt!", 1248 ); 1249 } 1250 1251 return 0; 1252 } 1253 1254 static int smu7_disable_sclk_mclk_dpm(struct pp_hwmgr *hwmgr) 1255 { 1256 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 1257 1258 /* disable SCLK dpm */ 1259 if (!data->sclk_dpm_key_disabled) { 1260 PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr), 1261 "Trying to disable SCLK DPM when DPM is disabled", 1262 return 0); 1263 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_DPM_Disable, NULL); 1264 } 1265 1266 /* disable MCLK dpm */ 1267 if (!data->mclk_dpm_key_disabled) { 1268 PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr), 1269 "Trying to disable MCLK DPM when DPM is disabled", 1270 return 0); 1271 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_MCLKDPM_Disable, NULL); 1272 } 1273 1274 return 0; 1275 } 1276 1277 static int smu7_stop_dpm(struct pp_hwmgr *hwmgr) 1278 { 1279 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 1280 1281 /* disable general power management */ 1282 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, GENERAL_PWRMGT, 1283 GLOBAL_PWRMGT_EN, 0); 1284 /* disable sclk deep sleep */ 1285 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SCLK_PWRMGT_CNTL, 1286 DYNAMIC_PM_EN, 0); 1287 1288 /* disable PCIE dpm */ 1289 if (!data->pcie_dpm_key_disabled) { 1290 PP_ASSERT_WITH_CODE( 1291 (smum_send_msg_to_smc(hwmgr, 1292 PPSMC_MSG_PCIeDPM_Disable, 1293 NULL) == 0), 1294 "Failed to disable pcie DPM during DPM Stop Function!", 1295 return -EINVAL); 1296 } 1297 1298 smu7_disable_sclk_mclk_dpm(hwmgr); 1299 1300 PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr), 1301 "Trying to disable voltage DPM when DPM is disabled", 1302 return 0); 1303 1304 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_Voltage_Cntl_Disable, NULL); 1305 1306 return 0; 1307 } 1308 1309 static void smu7_set_dpm_event_sources(struct pp_hwmgr *hwmgr, uint32_t sources) 1310 { 1311 bool protection; 1312 enum DPM_EVENT_SRC src; 1313 1314 switch (sources) { 1315 default: 1316 pr_err("Unknown throttling event sources."); 1317 fallthrough; 1318 case 0: 1319 protection = false; 1320 /* src is unused */ 1321 break; 1322 case (1 << PHM_AutoThrottleSource_Thermal): 1323 protection = true; 1324 src = DPM_EVENT_SRC_DIGITAL; 1325 break; 1326 case (1 << PHM_AutoThrottleSource_External): 1327 protection = true; 1328 src = DPM_EVENT_SRC_EXTERNAL; 1329 break; 1330 case (1 << PHM_AutoThrottleSource_External) | 1331 (1 << PHM_AutoThrottleSource_Thermal): 1332 protection = true; 1333 src = DPM_EVENT_SRC_DIGITAL_OR_EXTERNAL; 1334 break; 1335 } 1336 /* Order matters - don't enable thermal protection for the wrong source. */ 1337 if (protection) { 1338 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_THERMAL_CTRL, 1339 DPM_EVENT_SRC, src); 1340 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, GENERAL_PWRMGT, 1341 THERMAL_PROTECTION_DIS, 1342 !phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, 1343 PHM_PlatformCaps_ThermalController)); 1344 } else 1345 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, GENERAL_PWRMGT, 1346 THERMAL_PROTECTION_DIS, 1); 1347 } 1348 1349 static int smu7_enable_auto_throttle_source(struct pp_hwmgr *hwmgr, 1350 PHM_AutoThrottleSource source) 1351 { 1352 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 1353 1354 if (!(data->active_auto_throttle_sources & (1 << source))) { 1355 data->active_auto_throttle_sources |= 1 << source; 1356 smu7_set_dpm_event_sources(hwmgr, data->active_auto_throttle_sources); 1357 } 1358 return 0; 1359 } 1360 1361 static int smu7_enable_thermal_auto_throttle(struct pp_hwmgr *hwmgr) 1362 { 1363 return smu7_enable_auto_throttle_source(hwmgr, PHM_AutoThrottleSource_Thermal); 1364 } 1365 1366 static int smu7_disable_auto_throttle_source(struct pp_hwmgr *hwmgr, 1367 PHM_AutoThrottleSource source) 1368 { 1369 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 1370 1371 if (data->active_auto_throttle_sources & (1 << source)) { 1372 data->active_auto_throttle_sources &= ~(1 << source); 1373 smu7_set_dpm_event_sources(hwmgr, data->active_auto_throttle_sources); 1374 } 1375 return 0; 1376 } 1377 1378 static int smu7_disable_thermal_auto_throttle(struct pp_hwmgr *hwmgr) 1379 { 1380 return smu7_disable_auto_throttle_source(hwmgr, PHM_AutoThrottleSource_Thermal); 1381 } 1382 1383 static int smu7_pcie_performance_request(struct pp_hwmgr *hwmgr) 1384 { 1385 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 1386 data->pcie_performance_request = true; 1387 1388 return 0; 1389 } 1390 1391 static int smu7_enable_dpm_tasks(struct pp_hwmgr *hwmgr) 1392 { 1393 int tmp_result = 0; 1394 int result = 0; 1395 1396 if (smu7_voltage_control(hwmgr)) { 1397 tmp_result = smu7_enable_voltage_control(hwmgr); 1398 PP_ASSERT_WITH_CODE(tmp_result == 0, 1399 "Failed to enable voltage control!", 1400 result = tmp_result); 1401 1402 tmp_result = smu7_construct_voltage_tables(hwmgr); 1403 PP_ASSERT_WITH_CODE((0 == tmp_result), 1404 "Failed to construct voltage tables!", 1405 result = tmp_result); 1406 } 1407 smum_initialize_mc_reg_table(hwmgr); 1408 1409 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, 1410 PHM_PlatformCaps_EngineSpreadSpectrumSupport)) 1411 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, 1412 GENERAL_PWRMGT, DYN_SPREAD_SPECTRUM_EN, 1); 1413 1414 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, 1415 PHM_PlatformCaps_ThermalController)) 1416 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, 1417 GENERAL_PWRMGT, THERMAL_PROTECTION_DIS, 0); 1418 1419 tmp_result = smu7_program_static_screen_threshold_parameters(hwmgr); 1420 PP_ASSERT_WITH_CODE((0 == tmp_result), 1421 "Failed to program static screen threshold parameters!", 1422 result = tmp_result); 1423 1424 tmp_result = smu7_enable_display_gap(hwmgr); 1425 PP_ASSERT_WITH_CODE((0 == tmp_result), 1426 "Failed to enable display gap!", result = tmp_result); 1427 1428 tmp_result = smu7_program_voting_clients(hwmgr); 1429 PP_ASSERT_WITH_CODE((0 == tmp_result), 1430 "Failed to program voting clients!", result = tmp_result); 1431 1432 tmp_result = smum_process_firmware_header(hwmgr); 1433 PP_ASSERT_WITH_CODE((0 == tmp_result), 1434 "Failed to process firmware header!", result = tmp_result); 1435 1436 if (hwmgr->chip_id != CHIP_VEGAM) { 1437 tmp_result = smu7_initial_switch_from_arbf0_to_f1(hwmgr); 1438 PP_ASSERT_WITH_CODE((0 == tmp_result), 1439 "Failed to initialize switch from ArbF0 to F1!", 1440 result = tmp_result); 1441 } 1442 1443 result = smu7_setup_default_dpm_tables(hwmgr); 1444 PP_ASSERT_WITH_CODE(0 == result, 1445 "Failed to setup default DPM tables!", return result); 1446 1447 tmp_result = smum_init_smc_table(hwmgr); 1448 PP_ASSERT_WITH_CODE((0 == tmp_result), 1449 "Failed to initialize SMC table!", result = tmp_result); 1450 1451 tmp_result = smu7_enable_vrhot_gpio_interrupt(hwmgr); 1452 PP_ASSERT_WITH_CODE((0 == tmp_result), 1453 "Failed to enable VR hot GPIO interrupt!", result = tmp_result); 1454 1455 smum_send_msg_to_smc(hwmgr, (PPSMC_Msg)PPSMC_NoDisplay, NULL); 1456 1457 tmp_result = smu7_enable_sclk_control(hwmgr); 1458 PP_ASSERT_WITH_CODE((0 == tmp_result), 1459 "Failed to enable SCLK control!", result = tmp_result); 1460 1461 tmp_result = smu7_enable_smc_voltage_controller(hwmgr); 1462 PP_ASSERT_WITH_CODE((0 == tmp_result), 1463 "Failed to enable voltage control!", result = tmp_result); 1464 1465 tmp_result = smu7_enable_ulv(hwmgr); 1466 PP_ASSERT_WITH_CODE((0 == tmp_result), 1467 "Failed to enable ULV!", result = tmp_result); 1468 1469 tmp_result = smu7_enable_deep_sleep_master_switch(hwmgr); 1470 PP_ASSERT_WITH_CODE((0 == tmp_result), 1471 "Failed to enable deep sleep master switch!", result = tmp_result); 1472 1473 tmp_result = smu7_enable_didt_config(hwmgr); 1474 PP_ASSERT_WITH_CODE((tmp_result == 0), 1475 "Failed to enable deep sleep master switch!", result = tmp_result); 1476 1477 tmp_result = smu7_start_dpm(hwmgr); 1478 PP_ASSERT_WITH_CODE((0 == tmp_result), 1479 "Failed to start DPM!", result = tmp_result); 1480 1481 tmp_result = smu7_enable_smc_cac(hwmgr); 1482 PP_ASSERT_WITH_CODE((0 == tmp_result), 1483 "Failed to enable SMC CAC!", result = tmp_result); 1484 1485 tmp_result = smu7_enable_power_containment(hwmgr); 1486 PP_ASSERT_WITH_CODE((0 == tmp_result), 1487 "Failed to enable power containment!", result = tmp_result); 1488 1489 tmp_result = smu7_power_control_set_level(hwmgr); 1490 PP_ASSERT_WITH_CODE((0 == tmp_result), 1491 "Failed to power control set level!", result = tmp_result); 1492 1493 tmp_result = smu7_enable_thermal_auto_throttle(hwmgr); 1494 PP_ASSERT_WITH_CODE((0 == tmp_result), 1495 "Failed to enable thermal auto throttle!", result = tmp_result); 1496 1497 tmp_result = smu7_pcie_performance_request(hwmgr); 1498 PP_ASSERT_WITH_CODE((0 == tmp_result), 1499 "pcie performance request failed!", result = tmp_result); 1500 1501 return 0; 1502 } 1503 1504 static int smu7_avfs_control(struct pp_hwmgr *hwmgr, bool enable) 1505 { 1506 if (!hwmgr->avfs_supported) 1507 return 0; 1508 1509 if (enable) { 1510 if (!PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, 1511 CGS_IND_REG__SMC, FEATURE_STATUS, AVS_ON)) { 1512 PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc( 1513 hwmgr, PPSMC_MSG_EnableAvfs, NULL), 1514 "Failed to enable AVFS!", 1515 return -EINVAL); 1516 } 1517 } else if (PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, 1518 CGS_IND_REG__SMC, FEATURE_STATUS, AVS_ON)) { 1519 PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc( 1520 hwmgr, PPSMC_MSG_DisableAvfs, NULL), 1521 "Failed to disable AVFS!", 1522 return -EINVAL); 1523 } 1524 1525 return 0; 1526 } 1527 1528 static int smu7_update_avfs(struct pp_hwmgr *hwmgr) 1529 { 1530 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 1531 1532 if (!hwmgr->avfs_supported) 1533 return 0; 1534 1535 if (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_VDDC) { 1536 smu7_avfs_control(hwmgr, false); 1537 } else if (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_SCLK) { 1538 smu7_avfs_control(hwmgr, false); 1539 smu7_avfs_control(hwmgr, true); 1540 } else { 1541 smu7_avfs_control(hwmgr, true); 1542 } 1543 1544 return 0; 1545 } 1546 1547 static int smu7_disable_dpm_tasks(struct pp_hwmgr *hwmgr) 1548 { 1549 int tmp_result, result = 0; 1550 1551 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, 1552 PHM_PlatformCaps_ThermalController)) 1553 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, 1554 GENERAL_PWRMGT, THERMAL_PROTECTION_DIS, 1); 1555 1556 tmp_result = smu7_disable_power_containment(hwmgr); 1557 PP_ASSERT_WITH_CODE((tmp_result == 0), 1558 "Failed to disable power containment!", result = tmp_result); 1559 1560 tmp_result = smu7_disable_smc_cac(hwmgr); 1561 PP_ASSERT_WITH_CODE((tmp_result == 0), 1562 "Failed to disable SMC CAC!", result = tmp_result); 1563 1564 tmp_result = smu7_disable_didt_config(hwmgr); 1565 PP_ASSERT_WITH_CODE((tmp_result == 0), 1566 "Failed to disable DIDT!", result = tmp_result); 1567 1568 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, 1569 CG_SPLL_SPREAD_SPECTRUM, SSEN, 0); 1570 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, 1571 GENERAL_PWRMGT, DYN_SPREAD_SPECTRUM_EN, 0); 1572 1573 tmp_result = smu7_disable_thermal_auto_throttle(hwmgr); 1574 PP_ASSERT_WITH_CODE((tmp_result == 0), 1575 "Failed to disable thermal auto throttle!", result = tmp_result); 1576 1577 tmp_result = smu7_avfs_control(hwmgr, false); 1578 PP_ASSERT_WITH_CODE((tmp_result == 0), 1579 "Failed to disable AVFS!", result = tmp_result); 1580 1581 tmp_result = smu7_stop_dpm(hwmgr); 1582 PP_ASSERT_WITH_CODE((tmp_result == 0), 1583 "Failed to stop DPM!", result = tmp_result); 1584 1585 tmp_result = smu7_disable_deep_sleep_master_switch(hwmgr); 1586 PP_ASSERT_WITH_CODE((tmp_result == 0), 1587 "Failed to disable deep sleep master switch!", result = tmp_result); 1588 1589 tmp_result = smu7_disable_ulv(hwmgr); 1590 PP_ASSERT_WITH_CODE((tmp_result == 0), 1591 "Failed to disable ULV!", result = tmp_result); 1592 1593 tmp_result = smu7_clear_voting_clients(hwmgr); 1594 PP_ASSERT_WITH_CODE((tmp_result == 0), 1595 "Failed to clear voting clients!", result = tmp_result); 1596 1597 tmp_result = smu7_reset_to_default(hwmgr); 1598 PP_ASSERT_WITH_CODE((tmp_result == 0), 1599 "Failed to reset to default!", result = tmp_result); 1600 1601 tmp_result = smum_stop_smc(hwmgr); 1602 PP_ASSERT_WITH_CODE((tmp_result == 0), 1603 "Failed to stop smc!", result = tmp_result); 1604 1605 tmp_result = smu7_force_switch_to_arbf0(hwmgr); 1606 PP_ASSERT_WITH_CODE((tmp_result == 0), 1607 "Failed to force to switch arbf0!", result = tmp_result); 1608 1609 return result; 1610 } 1611 1612 static bool intel_core_rkl_chk(void) 1613 { 1614 #if IS_ENABLED(CONFIG_X86_64) 1615 struct cpu_info *ci = curcpu(); 1616 1617 return (ci->ci_family == 6 && ci->ci_model == 0xa7); 1618 #else 1619 return false; 1620 #endif 1621 } 1622 1623 static void smu7_init_dpm_defaults(struct pp_hwmgr *hwmgr) 1624 { 1625 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 1626 struct phm_ppt_v1_information *table_info = 1627 (struct phm_ppt_v1_information *)(hwmgr->pptable); 1628 struct amdgpu_device *adev = hwmgr->adev; 1629 1630 data->dll_default_on = false; 1631 data->mclk_dpm0_activity_target = 0xa; 1632 data->vddc_vddgfx_delta = 300; 1633 data->static_screen_threshold = SMU7_STATICSCREENTHRESHOLD_DFLT; 1634 data->static_screen_threshold_unit = SMU7_STATICSCREENTHRESHOLDUNIT_DFLT; 1635 data->voting_rights_clients[0] = SMU7_VOTINGRIGHTSCLIENTS_DFLT0; 1636 data->voting_rights_clients[1]= SMU7_VOTINGRIGHTSCLIENTS_DFLT1; 1637 data->voting_rights_clients[2] = SMU7_VOTINGRIGHTSCLIENTS_DFLT2; 1638 data->voting_rights_clients[3]= SMU7_VOTINGRIGHTSCLIENTS_DFLT3; 1639 data->voting_rights_clients[4]= SMU7_VOTINGRIGHTSCLIENTS_DFLT4; 1640 data->voting_rights_clients[5]= SMU7_VOTINGRIGHTSCLIENTS_DFLT5; 1641 data->voting_rights_clients[6]= SMU7_VOTINGRIGHTSCLIENTS_DFLT6; 1642 data->voting_rights_clients[7]= SMU7_VOTINGRIGHTSCLIENTS_DFLT7; 1643 1644 data->mclk_dpm_key_disabled = hwmgr->feature_mask & PP_MCLK_DPM_MASK ? false : true; 1645 data->sclk_dpm_key_disabled = hwmgr->feature_mask & PP_SCLK_DPM_MASK ? false : true; 1646 data->pcie_dpm_key_disabled = 1647 intel_core_rkl_chk() || !(hwmgr->feature_mask & PP_PCIE_DPM_MASK); 1648 /* need to set voltage control types before EVV patching */ 1649 data->voltage_control = SMU7_VOLTAGE_CONTROL_NONE; 1650 data->vddci_control = SMU7_VOLTAGE_CONTROL_NONE; 1651 data->mvdd_control = SMU7_VOLTAGE_CONTROL_NONE; 1652 data->enable_tdc_limit_feature = true; 1653 data->enable_pkg_pwr_tracking_feature = true; 1654 data->force_pcie_gen = PP_PCIEGenInvalid; 1655 data->ulv_supported = hwmgr->feature_mask & PP_ULV_MASK ? true : false; 1656 data->current_profile_setting.bupdate_sclk = 1; 1657 data->current_profile_setting.sclk_up_hyst = 0; 1658 data->current_profile_setting.sclk_down_hyst = 100; 1659 data->current_profile_setting.sclk_activity = SMU7_SCLK_TARGETACTIVITY_DFLT; 1660 data->current_profile_setting.bupdate_mclk = 1; 1661 if (hwmgr->chip_id >= CHIP_POLARIS10) { 1662 if (adev->gmc.vram_width == 256) { 1663 data->current_profile_setting.mclk_up_hyst = 10; 1664 data->current_profile_setting.mclk_down_hyst = 60; 1665 data->current_profile_setting.mclk_activity = 25; 1666 } else if (adev->gmc.vram_width == 128) { 1667 data->current_profile_setting.mclk_up_hyst = 5; 1668 data->current_profile_setting.mclk_down_hyst = 16; 1669 data->current_profile_setting.mclk_activity = 20; 1670 } else if (adev->gmc.vram_width == 64) { 1671 data->current_profile_setting.mclk_up_hyst = 3; 1672 data->current_profile_setting.mclk_down_hyst = 16; 1673 data->current_profile_setting.mclk_activity = 20; 1674 } 1675 } else { 1676 data->current_profile_setting.mclk_up_hyst = 0; 1677 data->current_profile_setting.mclk_down_hyst = 100; 1678 data->current_profile_setting.mclk_activity = SMU7_MCLK_TARGETACTIVITY_DFLT; 1679 } 1680 hwmgr->workload_mask = 1 << hwmgr->workload_prority[PP_SMC_POWER_PROFILE_FULLSCREEN3D]; 1681 hwmgr->power_profile_mode = PP_SMC_POWER_PROFILE_FULLSCREEN3D; 1682 hwmgr->default_power_profile_mode = PP_SMC_POWER_PROFILE_FULLSCREEN3D; 1683 1684 if (hwmgr->chip_id == CHIP_POLARIS12 || hwmgr->is_kicker) { 1685 uint8_t tmp1, tmp2; 1686 uint16_t tmp3 = 0; 1687 atomctrl_get_svi2_info(hwmgr, VOLTAGE_TYPE_VDDC, &tmp1, &tmp2, 1688 &tmp3); 1689 tmp3 = (tmp3 >> 5) & 0x3; 1690 data->vddc_phase_shed_control = ((tmp3 << 1) | (tmp3 >> 1)) & 0x3; 1691 } else if (hwmgr->chip_family == AMDGPU_FAMILY_CI) { 1692 data->vddc_phase_shed_control = 1; 1693 } else { 1694 data->vddc_phase_shed_control = 0; 1695 } 1696 1697 if (hwmgr->chip_id == CHIP_HAWAII) { 1698 data->thermal_temp_setting.temperature_low = 94500; 1699 data->thermal_temp_setting.temperature_high = 95000; 1700 data->thermal_temp_setting.temperature_shutdown = 104000; 1701 } else { 1702 data->thermal_temp_setting.temperature_low = 99500; 1703 data->thermal_temp_setting.temperature_high = 100000; 1704 data->thermal_temp_setting.temperature_shutdown = 104000; 1705 } 1706 1707 data->fast_watermark_threshold = 100; 1708 if (atomctrl_is_voltage_controlled_by_gpio_v3(hwmgr, 1709 VOLTAGE_TYPE_VDDC, VOLTAGE_OBJ_SVID2)) 1710 data->voltage_control = SMU7_VOLTAGE_CONTROL_BY_SVID2; 1711 else if (atomctrl_is_voltage_controlled_by_gpio_v3(hwmgr, 1712 VOLTAGE_TYPE_VDDC, VOLTAGE_OBJ_GPIO_LUT)) 1713 data->voltage_control = SMU7_VOLTAGE_CONTROL_BY_GPIO; 1714 1715 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, 1716 PHM_PlatformCaps_ControlVDDGFX)) { 1717 if (atomctrl_is_voltage_controlled_by_gpio_v3(hwmgr, 1718 VOLTAGE_TYPE_VDDGFX, VOLTAGE_OBJ_SVID2)) { 1719 data->vdd_gfx_control = SMU7_VOLTAGE_CONTROL_BY_SVID2; 1720 } 1721 } 1722 1723 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, 1724 PHM_PlatformCaps_EnableMVDDControl)) { 1725 if (atomctrl_is_voltage_controlled_by_gpio_v3(hwmgr, 1726 VOLTAGE_TYPE_MVDDC, VOLTAGE_OBJ_GPIO_LUT)) 1727 data->mvdd_control = SMU7_VOLTAGE_CONTROL_BY_GPIO; 1728 else if (atomctrl_is_voltage_controlled_by_gpio_v3(hwmgr, 1729 VOLTAGE_TYPE_MVDDC, VOLTAGE_OBJ_SVID2)) 1730 data->mvdd_control = SMU7_VOLTAGE_CONTROL_BY_SVID2; 1731 } 1732 1733 if (SMU7_VOLTAGE_CONTROL_NONE == data->vdd_gfx_control) 1734 phm_cap_unset(hwmgr->platform_descriptor.platformCaps, 1735 PHM_PlatformCaps_ControlVDDGFX); 1736 1737 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, 1738 PHM_PlatformCaps_ControlVDDCI)) { 1739 if (atomctrl_is_voltage_controlled_by_gpio_v3(hwmgr, 1740 VOLTAGE_TYPE_VDDCI, VOLTAGE_OBJ_GPIO_LUT)) 1741 data->vddci_control = SMU7_VOLTAGE_CONTROL_BY_GPIO; 1742 else if (atomctrl_is_voltage_controlled_by_gpio_v3(hwmgr, 1743 VOLTAGE_TYPE_VDDCI, VOLTAGE_OBJ_SVID2)) 1744 data->vddci_control = SMU7_VOLTAGE_CONTROL_BY_SVID2; 1745 } 1746 1747 if (data->mvdd_control == SMU7_VOLTAGE_CONTROL_NONE) 1748 phm_cap_unset(hwmgr->platform_descriptor.platformCaps, 1749 PHM_PlatformCaps_EnableMVDDControl); 1750 1751 if (data->vddci_control == SMU7_VOLTAGE_CONTROL_NONE) 1752 phm_cap_unset(hwmgr->platform_descriptor.platformCaps, 1753 PHM_PlatformCaps_ControlVDDCI); 1754 1755 if ((hwmgr->pp_table_version != PP_TABLE_V0) && (hwmgr->feature_mask & PP_CLOCK_STRETCH_MASK) 1756 && (table_info->cac_dtp_table->usClockStretchAmount != 0)) 1757 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 1758 PHM_PlatformCaps_ClockStretcher); 1759 1760 data->pcie_gen_performance.max = PP_PCIEGen1; 1761 data->pcie_gen_performance.min = PP_PCIEGen3; 1762 data->pcie_gen_power_saving.max = PP_PCIEGen1; 1763 data->pcie_gen_power_saving.min = PP_PCIEGen3; 1764 data->pcie_lane_performance.max = 0; 1765 data->pcie_lane_performance.min = 16; 1766 data->pcie_lane_power_saving.max = 0; 1767 data->pcie_lane_power_saving.min = 16; 1768 1769 1770 if (adev->pg_flags & AMD_PG_SUPPORT_UVD) 1771 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 1772 PHM_PlatformCaps_UVDPowerGating); 1773 if (adev->pg_flags & AMD_PG_SUPPORT_VCE) 1774 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 1775 PHM_PlatformCaps_VCEPowerGating); 1776 } 1777 1778 /** 1779 * Get Leakage VDDC based on leakage ID. 1780 * 1781 * @param hwmgr the address of the powerplay hardware manager. 1782 * @return always 0 1783 */ 1784 static int smu7_get_evv_voltages(struct pp_hwmgr *hwmgr) 1785 { 1786 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 1787 uint16_t vv_id; 1788 uint16_t vddc = 0; 1789 uint16_t vddgfx = 0; 1790 uint16_t i, j; 1791 uint32_t sclk = 0; 1792 struct phm_ppt_v1_information *table_info = 1793 (struct phm_ppt_v1_information *)hwmgr->pptable; 1794 struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table = NULL; 1795 1796 1797 for (i = 0; i < SMU7_MAX_LEAKAGE_COUNT; i++) { 1798 vv_id = ATOM_VIRTUAL_VOLTAGE_ID0 + i; 1799 1800 if (data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID2) { 1801 if ((hwmgr->pp_table_version == PP_TABLE_V1) 1802 && !phm_get_sclk_for_voltage_evv(hwmgr, 1803 table_info->vddgfx_lookup_table, vv_id, &sclk)) { 1804 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, 1805 PHM_PlatformCaps_ClockStretcher)) { 1806 sclk_table = table_info->vdd_dep_on_sclk; 1807 1808 for (j = 1; j < sclk_table->count; j++) { 1809 if (sclk_table->entries[j].clk == sclk && 1810 sclk_table->entries[j].cks_enable == 0) { 1811 sclk += 5000; 1812 break; 1813 } 1814 } 1815 } 1816 if (0 == atomctrl_get_voltage_evv_on_sclk 1817 (hwmgr, VOLTAGE_TYPE_VDDGFX, sclk, 1818 vv_id, &vddgfx)) { 1819 /* need to make sure vddgfx is less than 2v or else, it could burn the ASIC. */ 1820 PP_ASSERT_WITH_CODE((vddgfx < 2000 && vddgfx != 0), "Invalid VDDGFX value!", return -EINVAL); 1821 1822 /* the voltage should not be zero nor equal to leakage ID */ 1823 if (vddgfx != 0 && vddgfx != vv_id) { 1824 data->vddcgfx_leakage.actual_voltage[data->vddcgfx_leakage.count] = vddgfx; 1825 data->vddcgfx_leakage.leakage_id[data->vddcgfx_leakage.count] = vv_id; 1826 data->vddcgfx_leakage.count++; 1827 } 1828 } else { 1829 pr_info("Error retrieving EVV voltage value!\n"); 1830 } 1831 } 1832 } else { 1833 if ((hwmgr->pp_table_version == PP_TABLE_V0) 1834 || !phm_get_sclk_for_voltage_evv(hwmgr, 1835 table_info->vddc_lookup_table, vv_id, &sclk)) { 1836 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, 1837 PHM_PlatformCaps_ClockStretcher)) { 1838 if (table_info == NULL) 1839 return -EINVAL; 1840 sclk_table = table_info->vdd_dep_on_sclk; 1841 1842 for (j = 1; j < sclk_table->count; j++) { 1843 if (sclk_table->entries[j].clk == sclk && 1844 sclk_table->entries[j].cks_enable == 0) { 1845 sclk += 5000; 1846 break; 1847 } 1848 } 1849 } 1850 1851 if (phm_get_voltage_evv_on_sclk(hwmgr, 1852 VOLTAGE_TYPE_VDDC, 1853 sclk, vv_id, &vddc) == 0) { 1854 if (vddc >= 2000 || vddc == 0) 1855 return -EINVAL; 1856 } else { 1857 pr_debug("failed to retrieving EVV voltage!\n"); 1858 continue; 1859 } 1860 1861 /* the voltage should not be zero nor equal to leakage ID */ 1862 if (vddc != 0 && vddc != vv_id) { 1863 data->vddc_leakage.actual_voltage[data->vddc_leakage.count] = (uint16_t)(vddc); 1864 data->vddc_leakage.leakage_id[data->vddc_leakage.count] = vv_id; 1865 data->vddc_leakage.count++; 1866 } 1867 } 1868 } 1869 } 1870 1871 return 0; 1872 } 1873 1874 /** 1875 * Change virtual leakage voltage to actual value. 1876 * 1877 * @param hwmgr the address of the powerplay hardware manager. 1878 * @param pointer to changing voltage 1879 * @param pointer to leakage table 1880 */ 1881 static void smu7_patch_ppt_v1_with_vdd_leakage(struct pp_hwmgr *hwmgr, 1882 uint16_t *voltage, struct smu7_leakage_voltage *leakage_table) 1883 { 1884 uint32_t index; 1885 1886 /* search for leakage voltage ID 0xff01 ~ 0xff08 */ 1887 for (index = 0; index < leakage_table->count; index++) { 1888 /* if this voltage matches a leakage voltage ID */ 1889 /* patch with actual leakage voltage */ 1890 if (leakage_table->leakage_id[index] == *voltage) { 1891 *voltage = leakage_table->actual_voltage[index]; 1892 break; 1893 } 1894 } 1895 1896 if (*voltage > ATOM_VIRTUAL_VOLTAGE_ID0) 1897 pr_err("Voltage value looks like a Leakage ID but it's not patched \n"); 1898 } 1899 1900 /** 1901 * Patch voltage lookup table by EVV leakages. 1902 * 1903 * @param hwmgr the address of the powerplay hardware manager. 1904 * @param pointer to voltage lookup table 1905 * @param pointer to leakage table 1906 * @return always 0 1907 */ 1908 static int smu7_patch_lookup_table_with_leakage(struct pp_hwmgr *hwmgr, 1909 phm_ppt_v1_voltage_lookup_table *lookup_table, 1910 struct smu7_leakage_voltage *leakage_table) 1911 { 1912 uint32_t i; 1913 1914 for (i = 0; i < lookup_table->count; i++) 1915 smu7_patch_ppt_v1_with_vdd_leakage(hwmgr, 1916 &lookup_table->entries[i].us_vdd, leakage_table); 1917 1918 return 0; 1919 } 1920 1921 static int smu7_patch_clock_voltage_limits_with_vddc_leakage( 1922 struct pp_hwmgr *hwmgr, struct smu7_leakage_voltage *leakage_table, 1923 uint16_t *vddc) 1924 { 1925 struct phm_ppt_v1_information *table_info = 1926 (struct phm_ppt_v1_information *)(hwmgr->pptable); 1927 smu7_patch_ppt_v1_with_vdd_leakage(hwmgr, (uint16_t *)vddc, leakage_table); 1928 hwmgr->dyn_state.max_clock_voltage_on_dc.vddc = 1929 table_info->max_clock_voltage_on_dc.vddc; 1930 return 0; 1931 } 1932 1933 static int smu7_patch_voltage_dependency_tables_with_lookup_table( 1934 struct pp_hwmgr *hwmgr) 1935 { 1936 uint8_t entry_id; 1937 uint8_t voltage_id; 1938 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 1939 struct phm_ppt_v1_information *table_info = 1940 (struct phm_ppt_v1_information *)(hwmgr->pptable); 1941 1942 struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table = 1943 table_info->vdd_dep_on_sclk; 1944 struct phm_ppt_v1_clock_voltage_dependency_table *mclk_table = 1945 table_info->vdd_dep_on_mclk; 1946 struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = 1947 table_info->mm_dep_table; 1948 1949 if (data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID2) { 1950 for (entry_id = 0; entry_id < sclk_table->count; ++entry_id) { 1951 voltage_id = sclk_table->entries[entry_id].vddInd; 1952 sclk_table->entries[entry_id].vddgfx = 1953 table_info->vddgfx_lookup_table->entries[voltage_id].us_vdd; 1954 } 1955 } else { 1956 for (entry_id = 0; entry_id < sclk_table->count; ++entry_id) { 1957 voltage_id = sclk_table->entries[entry_id].vddInd; 1958 sclk_table->entries[entry_id].vddc = 1959 table_info->vddc_lookup_table->entries[voltage_id].us_vdd; 1960 } 1961 } 1962 1963 for (entry_id = 0; entry_id < mclk_table->count; ++entry_id) { 1964 voltage_id = mclk_table->entries[entry_id].vddInd; 1965 mclk_table->entries[entry_id].vddc = 1966 table_info->vddc_lookup_table->entries[voltage_id].us_vdd; 1967 } 1968 1969 for (entry_id = 0; entry_id < mm_table->count; ++entry_id) { 1970 voltage_id = mm_table->entries[entry_id].vddcInd; 1971 mm_table->entries[entry_id].vddc = 1972 table_info->vddc_lookup_table->entries[voltage_id].us_vdd; 1973 } 1974 1975 return 0; 1976 1977 } 1978 1979 static int phm_add_voltage(struct pp_hwmgr *hwmgr, 1980 phm_ppt_v1_voltage_lookup_table *look_up_table, 1981 phm_ppt_v1_voltage_lookup_record *record) 1982 { 1983 uint32_t i; 1984 1985 PP_ASSERT_WITH_CODE((NULL != look_up_table), 1986 "Lookup Table empty.", return -EINVAL); 1987 PP_ASSERT_WITH_CODE((0 != look_up_table->count), 1988 "Lookup Table empty.", return -EINVAL); 1989 1990 i = smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_VDDGFX); 1991 PP_ASSERT_WITH_CODE((i >= look_up_table->count), 1992 "Lookup Table is full.", return -EINVAL); 1993 1994 /* This is to avoid entering duplicate calculated records. */ 1995 for (i = 0; i < look_up_table->count; i++) { 1996 if (look_up_table->entries[i].us_vdd == record->us_vdd) { 1997 if (look_up_table->entries[i].us_calculated == 1) 1998 return 0; 1999 break; 2000 } 2001 } 2002 2003 look_up_table->entries[i].us_calculated = 1; 2004 look_up_table->entries[i].us_vdd = record->us_vdd; 2005 look_up_table->entries[i].us_cac_low = record->us_cac_low; 2006 look_up_table->entries[i].us_cac_mid = record->us_cac_mid; 2007 look_up_table->entries[i].us_cac_high = record->us_cac_high; 2008 /* Only increment the count when we're appending, not replacing duplicate entry. */ 2009 if (i == look_up_table->count) 2010 look_up_table->count++; 2011 2012 return 0; 2013 } 2014 2015 2016 static int smu7_calc_voltage_dependency_tables(struct pp_hwmgr *hwmgr) 2017 { 2018 uint8_t entry_id; 2019 struct phm_ppt_v1_voltage_lookup_record v_record; 2020 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 2021 struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); 2022 2023 phm_ppt_v1_clock_voltage_dependency_table *sclk_table = pptable_info->vdd_dep_on_sclk; 2024 phm_ppt_v1_clock_voltage_dependency_table *mclk_table = pptable_info->vdd_dep_on_mclk; 2025 2026 if (data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID2) { 2027 for (entry_id = 0; entry_id < sclk_table->count; ++entry_id) { 2028 if (sclk_table->entries[entry_id].vdd_offset & (1 << 15)) 2029 v_record.us_vdd = sclk_table->entries[entry_id].vddgfx + 2030 sclk_table->entries[entry_id].vdd_offset - 0xFFFF; 2031 else 2032 v_record.us_vdd = sclk_table->entries[entry_id].vddgfx + 2033 sclk_table->entries[entry_id].vdd_offset; 2034 2035 sclk_table->entries[entry_id].vddc = 2036 v_record.us_cac_low = v_record.us_cac_mid = 2037 v_record.us_cac_high = v_record.us_vdd; 2038 2039 phm_add_voltage(hwmgr, pptable_info->vddc_lookup_table, &v_record); 2040 } 2041 2042 for (entry_id = 0; entry_id < mclk_table->count; ++entry_id) { 2043 if (mclk_table->entries[entry_id].vdd_offset & (1 << 15)) 2044 v_record.us_vdd = mclk_table->entries[entry_id].vddc + 2045 mclk_table->entries[entry_id].vdd_offset - 0xFFFF; 2046 else 2047 v_record.us_vdd = mclk_table->entries[entry_id].vddc + 2048 mclk_table->entries[entry_id].vdd_offset; 2049 2050 mclk_table->entries[entry_id].vddgfx = v_record.us_cac_low = 2051 v_record.us_cac_mid = v_record.us_cac_high = v_record.us_vdd; 2052 phm_add_voltage(hwmgr, pptable_info->vddgfx_lookup_table, &v_record); 2053 } 2054 } 2055 return 0; 2056 } 2057 2058 static int smu7_calc_mm_voltage_dependency_table(struct pp_hwmgr *hwmgr) 2059 { 2060 uint8_t entry_id; 2061 struct phm_ppt_v1_voltage_lookup_record v_record; 2062 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 2063 struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); 2064 phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = pptable_info->mm_dep_table; 2065 2066 if (data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID2) { 2067 for (entry_id = 0; entry_id < mm_table->count; entry_id++) { 2068 if (mm_table->entries[entry_id].vddgfx_offset & (1 << 15)) 2069 v_record.us_vdd = mm_table->entries[entry_id].vddc + 2070 mm_table->entries[entry_id].vddgfx_offset - 0xFFFF; 2071 else 2072 v_record.us_vdd = mm_table->entries[entry_id].vddc + 2073 mm_table->entries[entry_id].vddgfx_offset; 2074 2075 /* Add the calculated VDDGFX to the VDDGFX lookup table */ 2076 mm_table->entries[entry_id].vddgfx = v_record.us_cac_low = 2077 v_record.us_cac_mid = v_record.us_cac_high = v_record.us_vdd; 2078 phm_add_voltage(hwmgr, pptable_info->vddgfx_lookup_table, &v_record); 2079 } 2080 } 2081 return 0; 2082 } 2083 2084 static int smu7_sort_lookup_table(struct pp_hwmgr *hwmgr, 2085 struct phm_ppt_v1_voltage_lookup_table *lookup_table) 2086 { 2087 uint32_t table_size, i, j; 2088 table_size = lookup_table->count; 2089 2090 PP_ASSERT_WITH_CODE(0 != lookup_table->count, 2091 "Lookup table is empty", return -EINVAL); 2092 2093 /* Sorting voltages */ 2094 for (i = 0; i < table_size - 1; i++) { 2095 for (j = i + 1; j > 0; j--) { 2096 if (lookup_table->entries[j].us_vdd < 2097 lookup_table->entries[j - 1].us_vdd) { 2098 swap(lookup_table->entries[j - 1], 2099 lookup_table->entries[j]); 2100 } 2101 } 2102 } 2103 2104 return 0; 2105 } 2106 2107 static int smu7_complete_dependency_tables(struct pp_hwmgr *hwmgr) 2108 { 2109 int result = 0; 2110 int tmp_result; 2111 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 2112 struct phm_ppt_v1_information *table_info = 2113 (struct phm_ppt_v1_information *)(hwmgr->pptable); 2114 2115 if (data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID2) { 2116 tmp_result = smu7_patch_lookup_table_with_leakage(hwmgr, 2117 table_info->vddgfx_lookup_table, &(data->vddcgfx_leakage)); 2118 if (tmp_result != 0) 2119 result = tmp_result; 2120 2121 smu7_patch_ppt_v1_with_vdd_leakage(hwmgr, 2122 &table_info->max_clock_voltage_on_dc.vddgfx, &(data->vddcgfx_leakage)); 2123 } else { 2124 2125 tmp_result = smu7_patch_lookup_table_with_leakage(hwmgr, 2126 table_info->vddc_lookup_table, &(data->vddc_leakage)); 2127 if (tmp_result) 2128 result = tmp_result; 2129 2130 tmp_result = smu7_patch_clock_voltage_limits_with_vddc_leakage(hwmgr, 2131 &(data->vddc_leakage), &table_info->max_clock_voltage_on_dc.vddc); 2132 if (tmp_result) 2133 result = tmp_result; 2134 } 2135 2136 tmp_result = smu7_patch_voltage_dependency_tables_with_lookup_table(hwmgr); 2137 if (tmp_result) 2138 result = tmp_result; 2139 2140 tmp_result = smu7_calc_voltage_dependency_tables(hwmgr); 2141 if (tmp_result) 2142 result = tmp_result; 2143 2144 tmp_result = smu7_calc_mm_voltage_dependency_table(hwmgr); 2145 if (tmp_result) 2146 result = tmp_result; 2147 2148 tmp_result = smu7_sort_lookup_table(hwmgr, table_info->vddgfx_lookup_table); 2149 if (tmp_result) 2150 result = tmp_result; 2151 2152 tmp_result = smu7_sort_lookup_table(hwmgr, table_info->vddc_lookup_table); 2153 if (tmp_result) 2154 result = tmp_result; 2155 2156 return result; 2157 } 2158 2159 static int smu7_set_private_data_based_on_pptable_v1(struct pp_hwmgr *hwmgr) 2160 { 2161 struct phm_ppt_v1_information *table_info = 2162 (struct phm_ppt_v1_information *)(hwmgr->pptable); 2163 2164 struct phm_ppt_v1_clock_voltage_dependency_table *allowed_sclk_vdd_table = 2165 table_info->vdd_dep_on_sclk; 2166 struct phm_ppt_v1_clock_voltage_dependency_table *allowed_mclk_vdd_table = 2167 table_info->vdd_dep_on_mclk; 2168 2169 PP_ASSERT_WITH_CODE(allowed_sclk_vdd_table != NULL, 2170 "VDD dependency on SCLK table is missing.", 2171 return -EINVAL); 2172 PP_ASSERT_WITH_CODE(allowed_sclk_vdd_table->count >= 1, 2173 "VDD dependency on SCLK table has to have is missing.", 2174 return -EINVAL); 2175 2176 PP_ASSERT_WITH_CODE(allowed_mclk_vdd_table != NULL, 2177 "VDD dependency on MCLK table is missing", 2178 return -EINVAL); 2179 PP_ASSERT_WITH_CODE(allowed_mclk_vdd_table->count >= 1, 2180 "VDD dependency on MCLK table has to have is missing.", 2181 return -EINVAL); 2182 2183 table_info->max_clock_voltage_on_ac.sclk = 2184 allowed_sclk_vdd_table->entries[allowed_sclk_vdd_table->count - 1].clk; 2185 table_info->max_clock_voltage_on_ac.mclk = 2186 allowed_mclk_vdd_table->entries[allowed_mclk_vdd_table->count - 1].clk; 2187 table_info->max_clock_voltage_on_ac.vddc = 2188 allowed_sclk_vdd_table->entries[allowed_sclk_vdd_table->count - 1].vddc; 2189 table_info->max_clock_voltage_on_ac.vddci = 2190 allowed_mclk_vdd_table->entries[allowed_mclk_vdd_table->count - 1].vddci; 2191 2192 hwmgr->dyn_state.max_clock_voltage_on_ac.sclk = table_info->max_clock_voltage_on_ac.sclk; 2193 hwmgr->dyn_state.max_clock_voltage_on_ac.mclk = table_info->max_clock_voltage_on_ac.mclk; 2194 hwmgr->dyn_state.max_clock_voltage_on_ac.vddc = table_info->max_clock_voltage_on_ac.vddc; 2195 hwmgr->dyn_state.max_clock_voltage_on_ac.vddci = table_info->max_clock_voltage_on_ac.vddci; 2196 2197 return 0; 2198 } 2199 2200 static int smu7_patch_voltage_workaround(struct pp_hwmgr *hwmgr) 2201 { 2202 struct phm_ppt_v1_information *table_info = 2203 (struct phm_ppt_v1_information *)(hwmgr->pptable); 2204 struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table; 2205 struct phm_ppt_v1_voltage_lookup_table *lookup_table; 2206 uint32_t i; 2207 uint32_t hw_revision, sub_vendor_id, sub_sys_id; 2208 struct amdgpu_device *adev = hwmgr->adev; 2209 2210 if (table_info != NULL) { 2211 dep_mclk_table = table_info->vdd_dep_on_mclk; 2212 lookup_table = table_info->vddc_lookup_table; 2213 } else 2214 return 0; 2215 2216 hw_revision = adev->pdev->revision; 2217 sub_sys_id = adev->pdev->subsystem_device; 2218 sub_vendor_id = adev->pdev->subsystem_vendor; 2219 2220 if (hwmgr->chip_id == CHIP_POLARIS10 && hw_revision == 0xC7 && 2221 ((sub_sys_id == 0xb37 && sub_vendor_id == 0x1002) || 2222 (sub_sys_id == 0x4a8 && sub_vendor_id == 0x1043) || 2223 (sub_sys_id == 0x9480 && sub_vendor_id == 0x1682))) { 2224 if (lookup_table->entries[dep_mclk_table->entries[dep_mclk_table->count-1].vddInd].us_vdd >= 1000) 2225 return 0; 2226 2227 for (i = 0; i < lookup_table->count; i++) { 2228 if (lookup_table->entries[i].us_vdd < 0xff01 && lookup_table->entries[i].us_vdd >= 1000) { 2229 dep_mclk_table->entries[dep_mclk_table->count-1].vddInd = (uint8_t) i; 2230 return 0; 2231 } 2232 } 2233 } 2234 return 0; 2235 } 2236 2237 static int smu7_thermal_parameter_init(struct pp_hwmgr *hwmgr) 2238 { 2239 struct pp_atomctrl_gpio_pin_assignment gpio_pin_assignment; 2240 uint32_t temp_reg; 2241 struct phm_ppt_v1_information *table_info = 2242 (struct phm_ppt_v1_information *)(hwmgr->pptable); 2243 2244 2245 if (atomctrl_get_pp_assign_pin(hwmgr, VDDC_PCC_GPIO_PINID, &gpio_pin_assignment)) { 2246 temp_reg = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCNB_PWRMGT_CNTL); 2247 switch (gpio_pin_assignment.uc_gpio_pin_bit_shift) { 2248 case 0: 2249 temp_reg = PHM_SET_FIELD(temp_reg, CNB_PWRMGT_CNTL, GNB_SLOW_MODE, 0x1); 2250 break; 2251 case 1: 2252 temp_reg = PHM_SET_FIELD(temp_reg, CNB_PWRMGT_CNTL, GNB_SLOW_MODE, 0x2); 2253 break; 2254 case 2: 2255 temp_reg = PHM_SET_FIELD(temp_reg, CNB_PWRMGT_CNTL, GNB_SLOW, 0x1); 2256 break; 2257 case 3: 2258 temp_reg = PHM_SET_FIELD(temp_reg, CNB_PWRMGT_CNTL, FORCE_NB_PS1, 0x1); 2259 break; 2260 case 4: 2261 temp_reg = PHM_SET_FIELD(temp_reg, CNB_PWRMGT_CNTL, DPM_ENABLED, 0x1); 2262 break; 2263 default: 2264 break; 2265 } 2266 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCNB_PWRMGT_CNTL, temp_reg); 2267 } 2268 2269 if (table_info == NULL) 2270 return 0; 2271 2272 if (table_info->cac_dtp_table->usDefaultTargetOperatingTemp != 0 && 2273 hwmgr->thermal_controller.advanceFanControlParameters.ucFanControlMode) { 2274 hwmgr->thermal_controller.advanceFanControlParameters.usFanPWMMinLimit = 2275 (uint16_t)hwmgr->thermal_controller.advanceFanControlParameters.ucMinimumPWMLimit; 2276 2277 hwmgr->thermal_controller.advanceFanControlParameters.usFanPWMMaxLimit = 2278 (uint16_t)hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanPWM; 2279 2280 hwmgr->thermal_controller.advanceFanControlParameters.usFanPWMStep = 1; 2281 2282 hwmgr->thermal_controller.advanceFanControlParameters.usFanRPMMaxLimit = 100; 2283 2284 hwmgr->thermal_controller.advanceFanControlParameters.usFanRPMMinLimit = 2285 (uint16_t)hwmgr->thermal_controller.advanceFanControlParameters.ucMinimumPWMLimit; 2286 2287 hwmgr->thermal_controller.advanceFanControlParameters.usFanRPMStep = 1; 2288 2289 table_info->cac_dtp_table->usDefaultTargetOperatingTemp = (table_info->cac_dtp_table->usDefaultTargetOperatingTemp >= 50) ? 2290 (table_info->cac_dtp_table->usDefaultTargetOperatingTemp - 50) : 0; 2291 2292 table_info->cac_dtp_table->usOperatingTempMaxLimit = table_info->cac_dtp_table->usDefaultTargetOperatingTemp; 2293 table_info->cac_dtp_table->usOperatingTempStep = 1; 2294 table_info->cac_dtp_table->usOperatingTempHyst = 1; 2295 2296 hwmgr->thermal_controller.advanceFanControlParameters.usMaxFanPWM = 2297 hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanPWM; 2298 2299 hwmgr->thermal_controller.advanceFanControlParameters.usMaxFanRPM = 2300 hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanRPM; 2301 2302 hwmgr->dyn_state.cac_dtp_table->usOperatingTempMinLimit = 2303 table_info->cac_dtp_table->usOperatingTempMinLimit; 2304 2305 hwmgr->dyn_state.cac_dtp_table->usOperatingTempMaxLimit = 2306 table_info->cac_dtp_table->usOperatingTempMaxLimit; 2307 2308 hwmgr->dyn_state.cac_dtp_table->usDefaultTargetOperatingTemp = 2309 table_info->cac_dtp_table->usDefaultTargetOperatingTemp; 2310 2311 hwmgr->dyn_state.cac_dtp_table->usOperatingTempStep = 2312 table_info->cac_dtp_table->usOperatingTempStep; 2313 2314 hwmgr->dyn_state.cac_dtp_table->usTargetOperatingTemp = 2315 table_info->cac_dtp_table->usTargetOperatingTemp; 2316 if (hwmgr->feature_mask & PP_OD_FUZZY_FAN_CONTROL_MASK) 2317 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 2318 PHM_PlatformCaps_ODFuzzyFanControlSupport); 2319 } 2320 2321 return 0; 2322 } 2323 2324 /** 2325 * Change virtual leakage voltage to actual value. 2326 * 2327 * @param hwmgr the address of the powerplay hardware manager. 2328 * @param pointer to changing voltage 2329 * @param pointer to leakage table 2330 */ 2331 static void smu7_patch_ppt_v0_with_vdd_leakage(struct pp_hwmgr *hwmgr, 2332 uint32_t *voltage, struct smu7_leakage_voltage *leakage_table) 2333 { 2334 uint32_t index; 2335 2336 /* search for leakage voltage ID 0xff01 ~ 0xff08 */ 2337 for (index = 0; index < leakage_table->count; index++) { 2338 /* if this voltage matches a leakage voltage ID */ 2339 /* patch with actual leakage voltage */ 2340 if (leakage_table->leakage_id[index] == *voltage) { 2341 *voltage = leakage_table->actual_voltage[index]; 2342 break; 2343 } 2344 } 2345 2346 if (*voltage > ATOM_VIRTUAL_VOLTAGE_ID0) 2347 pr_err("Voltage value looks like a Leakage ID but it's not patched \n"); 2348 } 2349 2350 2351 static int smu7_patch_vddc(struct pp_hwmgr *hwmgr, 2352 struct phm_clock_voltage_dependency_table *tab) 2353 { 2354 uint16_t i; 2355 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 2356 2357 if (tab) 2358 for (i = 0; i < tab->count; i++) 2359 smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &tab->entries[i].v, 2360 &data->vddc_leakage); 2361 2362 return 0; 2363 } 2364 2365 static int smu7_patch_vddci(struct pp_hwmgr *hwmgr, 2366 struct phm_clock_voltage_dependency_table *tab) 2367 { 2368 uint16_t i; 2369 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 2370 2371 if (tab) 2372 for (i = 0; i < tab->count; i++) 2373 smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &tab->entries[i].v, 2374 &data->vddci_leakage); 2375 2376 return 0; 2377 } 2378 2379 static int smu7_patch_vce_vddc(struct pp_hwmgr *hwmgr, 2380 struct phm_vce_clock_voltage_dependency_table *tab) 2381 { 2382 uint16_t i; 2383 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 2384 2385 if (tab) 2386 for (i = 0; i < tab->count; i++) 2387 smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &tab->entries[i].v, 2388 &data->vddc_leakage); 2389 2390 return 0; 2391 } 2392 2393 2394 static int smu7_patch_uvd_vddc(struct pp_hwmgr *hwmgr, 2395 struct phm_uvd_clock_voltage_dependency_table *tab) 2396 { 2397 uint16_t i; 2398 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 2399 2400 if (tab) 2401 for (i = 0; i < tab->count; i++) 2402 smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &tab->entries[i].v, 2403 &data->vddc_leakage); 2404 2405 return 0; 2406 } 2407 2408 static int smu7_patch_vddc_shed_limit(struct pp_hwmgr *hwmgr, 2409 struct phm_phase_shedding_limits_table *tab) 2410 { 2411 uint16_t i; 2412 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 2413 2414 if (tab) 2415 for (i = 0; i < tab->count; i++) 2416 smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &tab->entries[i].Voltage, 2417 &data->vddc_leakage); 2418 2419 return 0; 2420 } 2421 2422 static int smu7_patch_samu_vddc(struct pp_hwmgr *hwmgr, 2423 struct phm_samu_clock_voltage_dependency_table *tab) 2424 { 2425 uint16_t i; 2426 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 2427 2428 if (tab) 2429 for (i = 0; i < tab->count; i++) 2430 smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &tab->entries[i].v, 2431 &data->vddc_leakage); 2432 2433 return 0; 2434 } 2435 2436 static int smu7_patch_acp_vddc(struct pp_hwmgr *hwmgr, 2437 struct phm_acp_clock_voltage_dependency_table *tab) 2438 { 2439 uint16_t i; 2440 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 2441 2442 if (tab) 2443 for (i = 0; i < tab->count; i++) 2444 smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &tab->entries[i].v, 2445 &data->vddc_leakage); 2446 2447 return 0; 2448 } 2449 2450 static int smu7_patch_limits_vddc(struct pp_hwmgr *hwmgr, 2451 struct phm_clock_and_voltage_limits *tab) 2452 { 2453 uint32_t vddc, vddci; 2454 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 2455 2456 if (tab) { 2457 vddc = tab->vddc; 2458 smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &vddc, 2459 &data->vddc_leakage); 2460 tab->vddc = vddc; 2461 vddci = tab->vddci; 2462 smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &vddci, 2463 &data->vddci_leakage); 2464 tab->vddci = vddci; 2465 } 2466 2467 return 0; 2468 } 2469 2470 static int smu7_patch_cac_vddc(struct pp_hwmgr *hwmgr, struct phm_cac_leakage_table *tab) 2471 { 2472 uint32_t i; 2473 uint32_t vddc; 2474 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 2475 2476 if (tab) { 2477 for (i = 0; i < tab->count; i++) { 2478 vddc = (uint32_t)(tab->entries[i].Vddc); 2479 smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &vddc, &data->vddc_leakage); 2480 tab->entries[i].Vddc = (uint16_t)vddc; 2481 } 2482 } 2483 2484 return 0; 2485 } 2486 2487 static int smu7_patch_dependency_tables_with_leakage(struct pp_hwmgr *hwmgr) 2488 { 2489 int tmp; 2490 2491 tmp = smu7_patch_vddc(hwmgr, hwmgr->dyn_state.vddc_dependency_on_sclk); 2492 if (tmp) 2493 return -EINVAL; 2494 2495 tmp = smu7_patch_vddc(hwmgr, hwmgr->dyn_state.vddc_dependency_on_mclk); 2496 if (tmp) 2497 return -EINVAL; 2498 2499 tmp = smu7_patch_vddc(hwmgr, hwmgr->dyn_state.vddc_dep_on_dal_pwrl); 2500 if (tmp) 2501 return -EINVAL; 2502 2503 tmp = smu7_patch_vddci(hwmgr, hwmgr->dyn_state.vddci_dependency_on_mclk); 2504 if (tmp) 2505 return -EINVAL; 2506 2507 tmp = smu7_patch_vce_vddc(hwmgr, hwmgr->dyn_state.vce_clock_voltage_dependency_table); 2508 if (tmp) 2509 return -EINVAL; 2510 2511 tmp = smu7_patch_uvd_vddc(hwmgr, hwmgr->dyn_state.uvd_clock_voltage_dependency_table); 2512 if (tmp) 2513 return -EINVAL; 2514 2515 tmp = smu7_patch_samu_vddc(hwmgr, hwmgr->dyn_state.samu_clock_voltage_dependency_table); 2516 if (tmp) 2517 return -EINVAL; 2518 2519 tmp = smu7_patch_acp_vddc(hwmgr, hwmgr->dyn_state.acp_clock_voltage_dependency_table); 2520 if (tmp) 2521 return -EINVAL; 2522 2523 tmp = smu7_patch_vddc_shed_limit(hwmgr, hwmgr->dyn_state.vddc_phase_shed_limits_table); 2524 if (tmp) 2525 return -EINVAL; 2526 2527 tmp = smu7_patch_limits_vddc(hwmgr, &hwmgr->dyn_state.max_clock_voltage_on_ac); 2528 if (tmp) 2529 return -EINVAL; 2530 2531 tmp = smu7_patch_limits_vddc(hwmgr, &hwmgr->dyn_state.max_clock_voltage_on_dc); 2532 if (tmp) 2533 return -EINVAL; 2534 2535 tmp = smu7_patch_cac_vddc(hwmgr, hwmgr->dyn_state.cac_leakage_table); 2536 if (tmp) 2537 return -EINVAL; 2538 2539 return 0; 2540 } 2541 2542 2543 static int smu7_set_private_data_based_on_pptable_v0(struct pp_hwmgr *hwmgr) 2544 { 2545 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 2546 2547 struct phm_clock_voltage_dependency_table *allowed_sclk_vddc_table = hwmgr->dyn_state.vddc_dependency_on_sclk; 2548 struct phm_clock_voltage_dependency_table *allowed_mclk_vddc_table = hwmgr->dyn_state.vddc_dependency_on_mclk; 2549 struct phm_clock_voltage_dependency_table *allowed_mclk_vddci_table = hwmgr->dyn_state.vddci_dependency_on_mclk; 2550 2551 PP_ASSERT_WITH_CODE(allowed_sclk_vddc_table != NULL, 2552 "VDDC dependency on SCLK table is missing. This table is mandatory", 2553 return -EINVAL); 2554 PP_ASSERT_WITH_CODE(allowed_sclk_vddc_table->count >= 1, 2555 "VDDC dependency on SCLK table has to have is missing. This table is mandatory", 2556 return -EINVAL); 2557 2558 PP_ASSERT_WITH_CODE(allowed_mclk_vddc_table != NULL, 2559 "VDDC dependency on MCLK table is missing. This table is mandatory", 2560 return -EINVAL); 2561 PP_ASSERT_WITH_CODE(allowed_mclk_vddc_table->count >= 1, 2562 "VDD dependency on MCLK table has to have is missing. This table is mandatory", 2563 return -EINVAL); 2564 2565 data->min_vddc_in_pptable = (uint16_t)allowed_sclk_vddc_table->entries[0].v; 2566 data->max_vddc_in_pptable = (uint16_t)allowed_sclk_vddc_table->entries[allowed_sclk_vddc_table->count - 1].v; 2567 2568 hwmgr->dyn_state.max_clock_voltage_on_ac.sclk = 2569 allowed_sclk_vddc_table->entries[allowed_sclk_vddc_table->count - 1].clk; 2570 hwmgr->dyn_state.max_clock_voltage_on_ac.mclk = 2571 allowed_mclk_vddc_table->entries[allowed_mclk_vddc_table->count - 1].clk; 2572 hwmgr->dyn_state.max_clock_voltage_on_ac.vddc = 2573 allowed_sclk_vddc_table->entries[allowed_sclk_vddc_table->count - 1].v; 2574 2575 if (allowed_mclk_vddci_table != NULL && allowed_mclk_vddci_table->count >= 1) { 2576 data->min_vddci_in_pptable = (uint16_t)allowed_mclk_vddci_table->entries[0].v; 2577 data->max_vddci_in_pptable = (uint16_t)allowed_mclk_vddci_table->entries[allowed_mclk_vddci_table->count - 1].v; 2578 } 2579 2580 if (hwmgr->dyn_state.vddci_dependency_on_mclk != NULL && hwmgr->dyn_state.vddci_dependency_on_mclk->count >= 1) 2581 hwmgr->dyn_state.max_clock_voltage_on_ac.vddci = hwmgr->dyn_state.vddci_dependency_on_mclk->entries[hwmgr->dyn_state.vddci_dependency_on_mclk->count - 1].v; 2582 2583 return 0; 2584 } 2585 2586 static int smu7_hwmgr_backend_fini(struct pp_hwmgr *hwmgr) 2587 { 2588 kfree(hwmgr->dyn_state.vddc_dep_on_dal_pwrl); 2589 hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL; 2590 kfree(hwmgr->backend); 2591 hwmgr->backend = NULL; 2592 2593 return 0; 2594 } 2595 2596 static int smu7_get_elb_voltages(struct pp_hwmgr *hwmgr) 2597 { 2598 uint16_t virtual_voltage_id, vddc, vddci, efuse_voltage_id; 2599 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 2600 int i; 2601 2602 if (atomctrl_get_leakage_id_from_efuse(hwmgr, &efuse_voltage_id) == 0) { 2603 for (i = 0; i < SMU7_MAX_LEAKAGE_COUNT; i++) { 2604 virtual_voltage_id = ATOM_VIRTUAL_VOLTAGE_ID0 + i; 2605 if (atomctrl_get_leakage_vddc_base_on_leakage(hwmgr, &vddc, &vddci, 2606 virtual_voltage_id, 2607 efuse_voltage_id) == 0) { 2608 if (vddc != 0 && vddc != virtual_voltage_id) { 2609 data->vddc_leakage.actual_voltage[data->vddc_leakage.count] = vddc; 2610 data->vddc_leakage.leakage_id[data->vddc_leakage.count] = virtual_voltage_id; 2611 data->vddc_leakage.count++; 2612 } 2613 if (vddci != 0 && vddci != virtual_voltage_id) { 2614 data->vddci_leakage.actual_voltage[data->vddci_leakage.count] = vddci; 2615 data->vddci_leakage.leakage_id[data->vddci_leakage.count] = virtual_voltage_id; 2616 data->vddci_leakage.count++; 2617 } 2618 } 2619 } 2620 } 2621 return 0; 2622 } 2623 2624 static int smu7_hwmgr_backend_init(struct pp_hwmgr *hwmgr) 2625 { 2626 struct smu7_hwmgr *data; 2627 int result = 0; 2628 2629 data = kzalloc(sizeof(struct smu7_hwmgr), GFP_KERNEL); 2630 if (data == NULL) 2631 return -ENOMEM; 2632 2633 hwmgr->backend = data; 2634 smu7_patch_voltage_workaround(hwmgr); 2635 smu7_init_dpm_defaults(hwmgr); 2636 2637 /* Get leakage voltage based on leakage ID. */ 2638 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, 2639 PHM_PlatformCaps_EVV)) { 2640 result = smu7_get_evv_voltages(hwmgr); 2641 if (result) { 2642 pr_info("Get EVV Voltage Failed. Abort Driver loading!\n"); 2643 return -EINVAL; 2644 } 2645 } else { 2646 smu7_get_elb_voltages(hwmgr); 2647 } 2648 2649 if (hwmgr->pp_table_version == PP_TABLE_V1) { 2650 smu7_complete_dependency_tables(hwmgr); 2651 smu7_set_private_data_based_on_pptable_v1(hwmgr); 2652 } else if (hwmgr->pp_table_version == PP_TABLE_V0) { 2653 smu7_patch_dependency_tables_with_leakage(hwmgr); 2654 smu7_set_private_data_based_on_pptable_v0(hwmgr); 2655 } 2656 2657 /* Initalize Dynamic State Adjustment Rule Settings */ 2658 result = phm_initializa_dynamic_state_adjustment_rule_settings(hwmgr); 2659 2660 if (0 == result) { 2661 struct amdgpu_device *adev = hwmgr->adev; 2662 2663 data->is_tlu_enabled = false; 2664 2665 hwmgr->platform_descriptor.hardwareActivityPerformanceLevels = 2666 SMU7_MAX_HARDWARE_POWERLEVELS; 2667 hwmgr->platform_descriptor.hardwarePerformanceLevels = 2; 2668 hwmgr->platform_descriptor.minimumClocksReductionPercentage = 50; 2669 2670 data->pcie_gen_cap = adev->pm.pcie_gen_mask; 2671 if (data->pcie_gen_cap & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3) 2672 data->pcie_spc_cap = 20; 2673 data->pcie_lane_cap = adev->pm.pcie_mlw_mask; 2674 2675 hwmgr->platform_descriptor.vbiosInterruptId = 0x20000400; /* IRQ_SOURCE1_SW_INT */ 2676 /* The true clock step depends on the frequency, typically 4.5 or 9 MHz. Here we use 5. */ 2677 hwmgr->platform_descriptor.clockStep.engineClock = 500; 2678 hwmgr->platform_descriptor.clockStep.memoryClock = 500; 2679 smu7_thermal_parameter_init(hwmgr); 2680 } else { 2681 /* Ignore return value in here, we are cleaning up a mess. */ 2682 smu7_hwmgr_backend_fini(hwmgr); 2683 } 2684 2685 return 0; 2686 } 2687 2688 static int smu7_force_dpm_highest(struct pp_hwmgr *hwmgr) 2689 { 2690 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 2691 uint32_t level, tmp; 2692 2693 if (!data->pcie_dpm_key_disabled) { 2694 if (data->dpm_level_enable_mask.pcie_dpm_enable_mask) { 2695 level = 0; 2696 tmp = data->dpm_level_enable_mask.pcie_dpm_enable_mask; 2697 while (tmp >>= 1) 2698 level++; 2699 2700 if (level) 2701 smum_send_msg_to_smc_with_parameter(hwmgr, 2702 PPSMC_MSG_PCIeDPM_ForceLevel, level, 2703 NULL); 2704 } 2705 } 2706 2707 if (!data->sclk_dpm_key_disabled) { 2708 if (data->dpm_level_enable_mask.sclk_dpm_enable_mask) { 2709 level = 0; 2710 tmp = data->dpm_level_enable_mask.sclk_dpm_enable_mask; 2711 while (tmp >>= 1) 2712 level++; 2713 2714 if (level) 2715 smum_send_msg_to_smc_with_parameter(hwmgr, 2716 PPSMC_MSG_SCLKDPM_SetEnabledMask, 2717 (1 << level), 2718 NULL); 2719 } 2720 } 2721 2722 if (!data->mclk_dpm_key_disabled) { 2723 if (data->dpm_level_enable_mask.mclk_dpm_enable_mask) { 2724 level = 0; 2725 tmp = data->dpm_level_enable_mask.mclk_dpm_enable_mask; 2726 while (tmp >>= 1) 2727 level++; 2728 2729 if (level) 2730 smum_send_msg_to_smc_with_parameter(hwmgr, 2731 PPSMC_MSG_MCLKDPM_SetEnabledMask, 2732 (1 << level), 2733 NULL); 2734 } 2735 } 2736 2737 return 0; 2738 } 2739 2740 static int smu7_upload_dpm_level_enable_mask(struct pp_hwmgr *hwmgr) 2741 { 2742 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 2743 2744 if (hwmgr->pp_table_version == PP_TABLE_V1) 2745 phm_apply_dal_min_voltage_request(hwmgr); 2746 /* TO DO for v0 iceland and Ci*/ 2747 2748 if (!data->sclk_dpm_key_disabled) { 2749 if (data->dpm_level_enable_mask.sclk_dpm_enable_mask) 2750 smum_send_msg_to_smc_with_parameter(hwmgr, 2751 PPSMC_MSG_SCLKDPM_SetEnabledMask, 2752 data->dpm_level_enable_mask.sclk_dpm_enable_mask, 2753 NULL); 2754 } 2755 2756 if (!data->mclk_dpm_key_disabled) { 2757 if (data->dpm_level_enable_mask.mclk_dpm_enable_mask) 2758 smum_send_msg_to_smc_with_parameter(hwmgr, 2759 PPSMC_MSG_MCLKDPM_SetEnabledMask, 2760 data->dpm_level_enable_mask.mclk_dpm_enable_mask, 2761 NULL); 2762 } 2763 2764 return 0; 2765 } 2766 2767 static int smu7_unforce_dpm_levels(struct pp_hwmgr *hwmgr) 2768 { 2769 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 2770 2771 if (!smum_is_dpm_running(hwmgr)) 2772 return -EINVAL; 2773 2774 if (!data->pcie_dpm_key_disabled) { 2775 smum_send_msg_to_smc(hwmgr, 2776 PPSMC_MSG_PCIeDPM_UnForceLevel, 2777 NULL); 2778 } 2779 2780 return smu7_upload_dpm_level_enable_mask(hwmgr); 2781 } 2782 2783 static int smu7_force_dpm_lowest(struct pp_hwmgr *hwmgr) 2784 { 2785 struct smu7_hwmgr *data = 2786 (struct smu7_hwmgr *)(hwmgr->backend); 2787 uint32_t level; 2788 2789 if (!data->sclk_dpm_key_disabled) 2790 if (data->dpm_level_enable_mask.sclk_dpm_enable_mask) { 2791 level = phm_get_lowest_enabled_level(hwmgr, 2792 data->dpm_level_enable_mask.sclk_dpm_enable_mask); 2793 smum_send_msg_to_smc_with_parameter(hwmgr, 2794 PPSMC_MSG_SCLKDPM_SetEnabledMask, 2795 (1 << level), 2796 NULL); 2797 2798 } 2799 2800 if (!data->mclk_dpm_key_disabled) { 2801 if (data->dpm_level_enable_mask.mclk_dpm_enable_mask) { 2802 level = phm_get_lowest_enabled_level(hwmgr, 2803 data->dpm_level_enable_mask.mclk_dpm_enable_mask); 2804 smum_send_msg_to_smc_with_parameter(hwmgr, 2805 PPSMC_MSG_MCLKDPM_SetEnabledMask, 2806 (1 << level), 2807 NULL); 2808 } 2809 } 2810 2811 if (!data->pcie_dpm_key_disabled) { 2812 if (data->dpm_level_enable_mask.pcie_dpm_enable_mask) { 2813 level = phm_get_lowest_enabled_level(hwmgr, 2814 data->dpm_level_enable_mask.pcie_dpm_enable_mask); 2815 smum_send_msg_to_smc_with_parameter(hwmgr, 2816 PPSMC_MSG_PCIeDPM_ForceLevel, 2817 (level), 2818 NULL); 2819 } 2820 } 2821 2822 return 0; 2823 } 2824 2825 static int smu7_get_profiling_clk(struct pp_hwmgr *hwmgr, enum amd_dpm_forced_level level, 2826 uint32_t *sclk_mask, uint32_t *mclk_mask, uint32_t *pcie_mask) 2827 { 2828 uint32_t percentage; 2829 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 2830 struct smu7_dpm_table *golden_dpm_table = &data->golden_dpm_table; 2831 int32_t tmp_mclk; 2832 int32_t tmp_sclk; 2833 int32_t count; 2834 2835 if (golden_dpm_table->mclk_table.count < 1) 2836 return -EINVAL; 2837 2838 percentage = 100 * golden_dpm_table->sclk_table.dpm_levels[golden_dpm_table->sclk_table.count - 1].value / 2839 golden_dpm_table->mclk_table.dpm_levels[golden_dpm_table->mclk_table.count - 1].value; 2840 2841 if (golden_dpm_table->mclk_table.count == 1) { 2842 percentage = 70; 2843 tmp_mclk = golden_dpm_table->mclk_table.dpm_levels[golden_dpm_table->mclk_table.count - 1].value; 2844 *mclk_mask = golden_dpm_table->mclk_table.count - 1; 2845 } else { 2846 tmp_mclk = golden_dpm_table->mclk_table.dpm_levels[golden_dpm_table->mclk_table.count - 2].value; 2847 *mclk_mask = golden_dpm_table->mclk_table.count - 2; 2848 } 2849 2850 tmp_sclk = tmp_mclk * percentage / 100; 2851 2852 if (hwmgr->pp_table_version == PP_TABLE_V0) { 2853 for (count = hwmgr->dyn_state.vddc_dependency_on_sclk->count-1; 2854 count >= 0; count--) { 2855 if (tmp_sclk >= hwmgr->dyn_state.vddc_dependency_on_sclk->entries[count].clk) { 2856 tmp_sclk = hwmgr->dyn_state.vddc_dependency_on_sclk->entries[count].clk; 2857 *sclk_mask = count; 2858 break; 2859 } 2860 } 2861 if (count < 0 || level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) { 2862 *sclk_mask = 0; 2863 tmp_sclk = hwmgr->dyn_state.vddc_dependency_on_sclk->entries[0].clk; 2864 } 2865 2866 if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) 2867 *sclk_mask = hwmgr->dyn_state.vddc_dependency_on_sclk->count-1; 2868 } else if (hwmgr->pp_table_version == PP_TABLE_V1) { 2869 struct phm_ppt_v1_information *table_info = 2870 (struct phm_ppt_v1_information *)(hwmgr->pptable); 2871 2872 for (count = table_info->vdd_dep_on_sclk->count-1; count >= 0; count--) { 2873 if (tmp_sclk >= table_info->vdd_dep_on_sclk->entries[count].clk) { 2874 tmp_sclk = table_info->vdd_dep_on_sclk->entries[count].clk; 2875 *sclk_mask = count; 2876 break; 2877 } 2878 } 2879 if (count < 0 || level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) { 2880 *sclk_mask = 0; 2881 tmp_sclk = table_info->vdd_dep_on_sclk->entries[0].clk; 2882 } 2883 2884 if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) 2885 *sclk_mask = table_info->vdd_dep_on_sclk->count - 1; 2886 } 2887 2888 if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) 2889 *mclk_mask = 0; 2890 else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) 2891 *mclk_mask = golden_dpm_table->mclk_table.count - 1; 2892 2893 *pcie_mask = data->dpm_table.pcie_speed_table.count - 1; 2894 hwmgr->pstate_sclk = tmp_sclk; 2895 hwmgr->pstate_mclk = tmp_mclk; 2896 2897 return 0; 2898 } 2899 2900 static int smu7_force_dpm_level(struct pp_hwmgr *hwmgr, 2901 enum amd_dpm_forced_level level) 2902 { 2903 int ret = 0; 2904 uint32_t sclk_mask = 0; 2905 uint32_t mclk_mask = 0; 2906 uint32_t pcie_mask = 0; 2907 2908 if (hwmgr->pstate_sclk == 0) 2909 smu7_get_profiling_clk(hwmgr, level, &sclk_mask, &mclk_mask, &pcie_mask); 2910 2911 switch (level) { 2912 case AMD_DPM_FORCED_LEVEL_HIGH: 2913 ret = smu7_force_dpm_highest(hwmgr); 2914 break; 2915 case AMD_DPM_FORCED_LEVEL_LOW: 2916 ret = smu7_force_dpm_lowest(hwmgr); 2917 break; 2918 case AMD_DPM_FORCED_LEVEL_AUTO: 2919 ret = smu7_unforce_dpm_levels(hwmgr); 2920 break; 2921 case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: 2922 case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK: 2923 case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK: 2924 case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK: 2925 ret = smu7_get_profiling_clk(hwmgr, level, &sclk_mask, &mclk_mask, &pcie_mask); 2926 if (ret) 2927 return ret; 2928 smu7_force_clock_level(hwmgr, PP_SCLK, 1<<sclk_mask); 2929 smu7_force_clock_level(hwmgr, PP_MCLK, 1<<mclk_mask); 2930 smu7_force_clock_level(hwmgr, PP_PCIE, 1<<pcie_mask); 2931 break; 2932 case AMD_DPM_FORCED_LEVEL_MANUAL: 2933 case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT: 2934 default: 2935 break; 2936 } 2937 2938 if (!ret) { 2939 if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK && hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) 2940 smu7_fan_ctrl_set_fan_speed_percent(hwmgr, 100); 2941 else if (level != AMD_DPM_FORCED_LEVEL_PROFILE_PEAK && hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) 2942 smu7_fan_ctrl_reset_fan_speed_to_default(hwmgr); 2943 } 2944 return ret; 2945 } 2946 2947 static int smu7_get_power_state_size(struct pp_hwmgr *hwmgr) 2948 { 2949 return sizeof(struct smu7_power_state); 2950 } 2951 2952 static int smu7_vblank_too_short(struct pp_hwmgr *hwmgr, 2953 uint32_t vblank_time_us) 2954 { 2955 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 2956 uint32_t switch_limit_us; 2957 2958 switch (hwmgr->chip_id) { 2959 case CHIP_POLARIS10: 2960 case CHIP_POLARIS11: 2961 case CHIP_POLARIS12: 2962 if (hwmgr->is_kicker) 2963 switch_limit_us = data->is_memory_gddr5 ? 450 : 150; 2964 else 2965 switch_limit_us = data->is_memory_gddr5 ? 200 : 150; 2966 break; 2967 case CHIP_VEGAM: 2968 switch_limit_us = 30; 2969 break; 2970 default: 2971 switch_limit_us = data->is_memory_gddr5 ? 450 : 150; 2972 break; 2973 } 2974 2975 if (vblank_time_us < switch_limit_us) 2976 return true; 2977 else 2978 return false; 2979 } 2980 2981 static int smu7_apply_state_adjust_rules(struct pp_hwmgr *hwmgr, 2982 struct pp_power_state *request_ps, 2983 const struct pp_power_state *current_ps) 2984 { 2985 struct amdgpu_device *adev = hwmgr->adev; 2986 struct smu7_power_state *smu7_ps = 2987 cast_phw_smu7_power_state(&request_ps->hardware); 2988 uint32_t sclk; 2989 uint32_t mclk; 2990 struct PP_Clocks minimum_clocks = {0}; 2991 bool disable_mclk_switching; 2992 bool disable_mclk_switching_for_frame_lock; 2993 const struct phm_clock_and_voltage_limits *max_limits; 2994 uint32_t i; 2995 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 2996 struct phm_ppt_v1_information *table_info = 2997 (struct phm_ppt_v1_information *)(hwmgr->pptable); 2998 int32_t count; 2999 int32_t stable_pstate_sclk = 0, stable_pstate_mclk = 0; 3000 3001 data->battery_state = (PP_StateUILabel_Battery == 3002 request_ps->classification.ui_label); 3003 3004 PP_ASSERT_WITH_CODE(smu7_ps->performance_level_count == 2, 3005 "VI should always have 2 performance levels", 3006 ); 3007 3008 max_limits = adev->pm.ac_power ? 3009 &(hwmgr->dyn_state.max_clock_voltage_on_ac) : 3010 &(hwmgr->dyn_state.max_clock_voltage_on_dc); 3011 3012 /* Cap clock DPM tables at DC MAX if it is in DC. */ 3013 if (!adev->pm.ac_power) { 3014 for (i = 0; i < smu7_ps->performance_level_count; i++) { 3015 if (smu7_ps->performance_levels[i].memory_clock > max_limits->mclk) 3016 smu7_ps->performance_levels[i].memory_clock = max_limits->mclk; 3017 if (smu7_ps->performance_levels[i].engine_clock > max_limits->sclk) 3018 smu7_ps->performance_levels[i].engine_clock = max_limits->sclk; 3019 } 3020 } 3021 3022 minimum_clocks.engineClock = hwmgr->display_config->min_core_set_clock; 3023 minimum_clocks.memoryClock = hwmgr->display_config->min_mem_set_clock; 3024 3025 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, 3026 PHM_PlatformCaps_StablePState)) { 3027 max_limits = &(hwmgr->dyn_state.max_clock_voltage_on_ac); 3028 stable_pstate_sclk = (max_limits->sclk * 75) / 100; 3029 3030 for (count = table_info->vdd_dep_on_sclk->count - 1; 3031 count >= 0; count--) { 3032 if (stable_pstate_sclk >= 3033 table_info->vdd_dep_on_sclk->entries[count].clk) { 3034 stable_pstate_sclk = 3035 table_info->vdd_dep_on_sclk->entries[count].clk; 3036 break; 3037 } 3038 } 3039 3040 if (count < 0) 3041 stable_pstate_sclk = table_info->vdd_dep_on_sclk->entries[0].clk; 3042 3043 stable_pstate_mclk = max_limits->mclk; 3044 3045 minimum_clocks.engineClock = stable_pstate_sclk; 3046 minimum_clocks.memoryClock = stable_pstate_mclk; 3047 } 3048 3049 disable_mclk_switching_for_frame_lock = phm_cap_enabled( 3050 hwmgr->platform_descriptor.platformCaps, 3051 PHM_PlatformCaps_DisableMclkSwitchingForFrameLock); 3052 3053 3054 if (hwmgr->display_config->num_display == 0) 3055 disable_mclk_switching = false; 3056 else 3057 disable_mclk_switching = ((1 < hwmgr->display_config->num_display) && 3058 !hwmgr->display_config->multi_monitor_in_sync) || 3059 disable_mclk_switching_for_frame_lock || 3060 smu7_vblank_too_short(hwmgr, hwmgr->display_config->min_vblank_time); 3061 3062 sclk = smu7_ps->performance_levels[0].engine_clock; 3063 mclk = smu7_ps->performance_levels[0].memory_clock; 3064 3065 if (disable_mclk_switching) 3066 mclk = smu7_ps->performance_levels 3067 [smu7_ps->performance_level_count - 1].memory_clock; 3068 3069 if (sclk < minimum_clocks.engineClock) 3070 sclk = (minimum_clocks.engineClock > max_limits->sclk) ? 3071 max_limits->sclk : minimum_clocks.engineClock; 3072 3073 if (mclk < minimum_clocks.memoryClock) 3074 mclk = (minimum_clocks.memoryClock > max_limits->mclk) ? 3075 max_limits->mclk : minimum_clocks.memoryClock; 3076 3077 smu7_ps->performance_levels[0].engine_clock = sclk; 3078 smu7_ps->performance_levels[0].memory_clock = mclk; 3079 3080 smu7_ps->performance_levels[1].engine_clock = 3081 (smu7_ps->performance_levels[1].engine_clock >= 3082 smu7_ps->performance_levels[0].engine_clock) ? 3083 smu7_ps->performance_levels[1].engine_clock : 3084 smu7_ps->performance_levels[0].engine_clock; 3085 3086 if (disable_mclk_switching) { 3087 if (mclk < smu7_ps->performance_levels[1].memory_clock) 3088 mclk = smu7_ps->performance_levels[1].memory_clock; 3089 3090 smu7_ps->performance_levels[0].memory_clock = mclk; 3091 smu7_ps->performance_levels[1].memory_clock = mclk; 3092 } else { 3093 if (smu7_ps->performance_levels[1].memory_clock < 3094 smu7_ps->performance_levels[0].memory_clock) 3095 smu7_ps->performance_levels[1].memory_clock = 3096 smu7_ps->performance_levels[0].memory_clock; 3097 } 3098 3099 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, 3100 PHM_PlatformCaps_StablePState)) { 3101 for (i = 0; i < smu7_ps->performance_level_count; i++) { 3102 smu7_ps->performance_levels[i].engine_clock = stable_pstate_sclk; 3103 smu7_ps->performance_levels[i].memory_clock = stable_pstate_mclk; 3104 smu7_ps->performance_levels[i].pcie_gen = data->pcie_gen_performance.max; 3105 smu7_ps->performance_levels[i].pcie_lane = data->pcie_gen_performance.max; 3106 } 3107 } 3108 return 0; 3109 } 3110 3111 3112 static uint32_t smu7_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low) 3113 { 3114 struct pp_power_state *ps; 3115 struct smu7_power_state *smu7_ps; 3116 3117 if (hwmgr == NULL) 3118 return -EINVAL; 3119 3120 ps = hwmgr->request_ps; 3121 3122 if (ps == NULL) 3123 return -EINVAL; 3124 3125 smu7_ps = cast_phw_smu7_power_state(&ps->hardware); 3126 3127 if (low) 3128 return smu7_ps->performance_levels[0].memory_clock; 3129 else 3130 return smu7_ps->performance_levels 3131 [smu7_ps->performance_level_count-1].memory_clock; 3132 } 3133 3134 static uint32_t smu7_dpm_get_sclk(struct pp_hwmgr *hwmgr, bool low) 3135 { 3136 struct pp_power_state *ps; 3137 struct smu7_power_state *smu7_ps; 3138 3139 if (hwmgr == NULL) 3140 return -EINVAL; 3141 3142 ps = hwmgr->request_ps; 3143 3144 if (ps == NULL) 3145 return -EINVAL; 3146 3147 smu7_ps = cast_phw_smu7_power_state(&ps->hardware); 3148 3149 if (low) 3150 return smu7_ps->performance_levels[0].engine_clock; 3151 else 3152 return smu7_ps->performance_levels 3153 [smu7_ps->performance_level_count-1].engine_clock; 3154 } 3155 3156 static int smu7_dpm_patch_boot_state(struct pp_hwmgr *hwmgr, 3157 struct pp_hw_power_state *hw_ps) 3158 { 3159 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 3160 struct smu7_power_state *ps = (struct smu7_power_state *)hw_ps; 3161 ATOM_FIRMWARE_INFO_V2_2 *fw_info; 3162 uint16_t size; 3163 uint8_t frev, crev; 3164 int index = GetIndexIntoMasterTable(DATA, FirmwareInfo); 3165 3166 /* First retrieve the Boot clocks and VDDC from the firmware info table. 3167 * We assume here that fw_info is unchanged if this call fails. 3168 */ 3169 fw_info = (ATOM_FIRMWARE_INFO_V2_2 *)smu_atom_get_data_table(hwmgr->adev, index, 3170 &size, &frev, &crev); 3171 if (!fw_info) 3172 /* During a test, there is no firmware info table. */ 3173 return 0; 3174 3175 /* Patch the state. */ 3176 data->vbios_boot_state.sclk_bootup_value = 3177 le32_to_cpu(fw_info->ulDefaultEngineClock); 3178 data->vbios_boot_state.mclk_bootup_value = 3179 le32_to_cpu(fw_info->ulDefaultMemoryClock); 3180 data->vbios_boot_state.mvdd_bootup_value = 3181 le16_to_cpu(fw_info->usBootUpMVDDCVoltage); 3182 data->vbios_boot_state.vddc_bootup_value = 3183 le16_to_cpu(fw_info->usBootUpVDDCVoltage); 3184 data->vbios_boot_state.vddci_bootup_value = 3185 le16_to_cpu(fw_info->usBootUpVDDCIVoltage); 3186 data->vbios_boot_state.pcie_gen_bootup_value = 3187 smu7_get_current_pcie_speed(hwmgr); 3188 3189 data->vbios_boot_state.pcie_lane_bootup_value = 3190 (uint16_t)smu7_get_current_pcie_lane_number(hwmgr); 3191 3192 /* set boot power state */ 3193 ps->performance_levels[0].memory_clock = data->vbios_boot_state.mclk_bootup_value; 3194 ps->performance_levels[0].engine_clock = data->vbios_boot_state.sclk_bootup_value; 3195 ps->performance_levels[0].pcie_gen = data->vbios_boot_state.pcie_gen_bootup_value; 3196 ps->performance_levels[0].pcie_lane = data->vbios_boot_state.pcie_lane_bootup_value; 3197 3198 return 0; 3199 } 3200 3201 static int smu7_get_number_of_powerplay_table_entries(struct pp_hwmgr *hwmgr) 3202 { 3203 int result; 3204 unsigned long ret = 0; 3205 3206 if (hwmgr->pp_table_version == PP_TABLE_V0) { 3207 result = pp_tables_get_num_of_entries(hwmgr, &ret); 3208 return result ? 0 : ret; 3209 } else if (hwmgr->pp_table_version == PP_TABLE_V1) { 3210 result = get_number_of_powerplay_table_entries_v1_0(hwmgr); 3211 return result; 3212 } 3213 return 0; 3214 } 3215 3216 static int smu7_get_pp_table_entry_callback_func_v1(struct pp_hwmgr *hwmgr, 3217 void *state, struct pp_power_state *power_state, 3218 void *pp_table, uint32_t classification_flag) 3219 { 3220 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 3221 struct smu7_power_state *smu7_power_state = 3222 (struct smu7_power_state *)(&(power_state->hardware)); 3223 struct smu7_performance_level *performance_level; 3224 ATOM_Tonga_State *state_entry = (ATOM_Tonga_State *)state; 3225 ATOM_Tonga_POWERPLAYTABLE *powerplay_table = 3226 (ATOM_Tonga_POWERPLAYTABLE *)pp_table; 3227 PPTable_Generic_SubTable_Header *sclk_dep_table = 3228 (PPTable_Generic_SubTable_Header *) 3229 (((unsigned long)powerplay_table) + 3230 le16_to_cpu(powerplay_table->usSclkDependencyTableOffset)); 3231 3232 ATOM_Tonga_MCLK_Dependency_Table *mclk_dep_table = 3233 (ATOM_Tonga_MCLK_Dependency_Table *) 3234 (((unsigned long)powerplay_table) + 3235 le16_to_cpu(powerplay_table->usMclkDependencyTableOffset)); 3236 3237 /* The following fields are not initialized here: id orderedList allStatesList */ 3238 power_state->classification.ui_label = 3239 (le16_to_cpu(state_entry->usClassification) & 3240 ATOM_PPLIB_CLASSIFICATION_UI_MASK) >> 3241 ATOM_PPLIB_CLASSIFICATION_UI_SHIFT; 3242 power_state->classification.flags = classification_flag; 3243 /* NOTE: There is a classification2 flag in BIOS that is not being used right now */ 3244 3245 power_state->classification.temporary_state = false; 3246 power_state->classification.to_be_deleted = false; 3247 3248 power_state->validation.disallowOnDC = 3249 (0 != (le32_to_cpu(state_entry->ulCapsAndSettings) & 3250 ATOM_Tonga_DISALLOW_ON_DC)); 3251 3252 power_state->pcie.lanes = 0; 3253 3254 power_state->display.disableFrameModulation = false; 3255 power_state->display.limitRefreshrate = false; 3256 power_state->display.enableVariBright = 3257 (0 != (le32_to_cpu(state_entry->ulCapsAndSettings) & 3258 ATOM_Tonga_ENABLE_VARIBRIGHT)); 3259 3260 power_state->validation.supportedPowerLevels = 0; 3261 power_state->uvd_clocks.VCLK = 0; 3262 power_state->uvd_clocks.DCLK = 0; 3263 power_state->temperatures.min = 0; 3264 power_state->temperatures.max = 0; 3265 3266 performance_level = &(smu7_power_state->performance_levels 3267 [smu7_power_state->performance_level_count++]); 3268 3269 PP_ASSERT_WITH_CODE( 3270 (smu7_power_state->performance_level_count < smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_GRAPHICS)), 3271 "Performance levels exceeds SMC limit!", 3272 return -EINVAL); 3273 3274 PP_ASSERT_WITH_CODE( 3275 (smu7_power_state->performance_level_count <= 3276 hwmgr->platform_descriptor.hardwareActivityPerformanceLevels), 3277 "Performance levels exceeds Driver limit!", 3278 return -EINVAL); 3279 3280 /* Performance levels are arranged from low to high. */ 3281 performance_level->memory_clock = mclk_dep_table->entries 3282 [state_entry->ucMemoryClockIndexLow].ulMclk; 3283 if (sclk_dep_table->ucRevId == 0) 3284 performance_level->engine_clock = ((ATOM_Tonga_SCLK_Dependency_Table *)sclk_dep_table)->entries 3285 [state_entry->ucEngineClockIndexLow].ulSclk; 3286 else if (sclk_dep_table->ucRevId == 1) 3287 performance_level->engine_clock = ((ATOM_Polaris_SCLK_Dependency_Table *)sclk_dep_table)->entries 3288 [state_entry->ucEngineClockIndexLow].ulSclk; 3289 performance_level->pcie_gen = get_pcie_gen_support(data->pcie_gen_cap, 3290 state_entry->ucPCIEGenLow); 3291 performance_level->pcie_lane = get_pcie_lane_support(data->pcie_lane_cap, 3292 state_entry->ucPCIELaneLow); 3293 3294 performance_level = &(smu7_power_state->performance_levels 3295 [smu7_power_state->performance_level_count++]); 3296 performance_level->memory_clock = mclk_dep_table->entries 3297 [state_entry->ucMemoryClockIndexHigh].ulMclk; 3298 3299 if (sclk_dep_table->ucRevId == 0) 3300 performance_level->engine_clock = ((ATOM_Tonga_SCLK_Dependency_Table *)sclk_dep_table)->entries 3301 [state_entry->ucEngineClockIndexHigh].ulSclk; 3302 else if (sclk_dep_table->ucRevId == 1) 3303 performance_level->engine_clock = ((ATOM_Polaris_SCLK_Dependency_Table *)sclk_dep_table)->entries 3304 [state_entry->ucEngineClockIndexHigh].ulSclk; 3305 3306 performance_level->pcie_gen = get_pcie_gen_support(data->pcie_gen_cap, 3307 state_entry->ucPCIEGenHigh); 3308 performance_level->pcie_lane = get_pcie_lane_support(data->pcie_lane_cap, 3309 state_entry->ucPCIELaneHigh); 3310 3311 return 0; 3312 } 3313 3314 static int smu7_get_pp_table_entry_v1(struct pp_hwmgr *hwmgr, 3315 unsigned long entry_index, struct pp_power_state *state) 3316 { 3317 int result; 3318 struct smu7_power_state *ps; 3319 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 3320 struct phm_ppt_v1_information *table_info = 3321 (struct phm_ppt_v1_information *)(hwmgr->pptable); 3322 struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table = 3323 table_info->vdd_dep_on_mclk; 3324 3325 state->hardware.magic = PHM_VIslands_Magic; 3326 3327 ps = (struct smu7_power_state *)(&state->hardware); 3328 3329 result = get_powerplay_table_entry_v1_0(hwmgr, entry_index, state, 3330 smu7_get_pp_table_entry_callback_func_v1); 3331 3332 /* This is the earliest time we have all the dependency table and the VBIOS boot state 3333 * as PP_Tables_GetPowerPlayTableEntry retrieves the VBIOS boot state 3334 * if there is only one VDDCI/MCLK level, check if it's the same as VBIOS boot state 3335 */ 3336 if (dep_mclk_table != NULL && dep_mclk_table->count == 1) { 3337 if (dep_mclk_table->entries[0].clk != 3338 data->vbios_boot_state.mclk_bootup_value) 3339 pr_debug("Single MCLK entry VDDCI/MCLK dependency table " 3340 "does not match VBIOS boot MCLK level"); 3341 if (dep_mclk_table->entries[0].vddci != 3342 data->vbios_boot_state.vddci_bootup_value) 3343 pr_debug("Single VDDCI entry VDDCI/MCLK dependency table " 3344 "does not match VBIOS boot VDDCI level"); 3345 } 3346 3347 /* set DC compatible flag if this state supports DC */ 3348 if (!state->validation.disallowOnDC) 3349 ps->dc_compatible = true; 3350 3351 if (state->classification.flags & PP_StateClassificationFlag_ACPI) 3352 data->acpi_pcie_gen = ps->performance_levels[0].pcie_gen; 3353 3354 ps->uvd_clks.vclk = state->uvd_clocks.VCLK; 3355 ps->uvd_clks.dclk = state->uvd_clocks.DCLK; 3356 3357 if (!result) { 3358 uint32_t i; 3359 3360 switch (state->classification.ui_label) { 3361 case PP_StateUILabel_Performance: 3362 data->use_pcie_performance_levels = true; 3363 for (i = 0; i < ps->performance_level_count; i++) { 3364 if (data->pcie_gen_performance.max < 3365 ps->performance_levels[i].pcie_gen) 3366 data->pcie_gen_performance.max = 3367 ps->performance_levels[i].pcie_gen; 3368 3369 if (data->pcie_gen_performance.min > 3370 ps->performance_levels[i].pcie_gen) 3371 data->pcie_gen_performance.min = 3372 ps->performance_levels[i].pcie_gen; 3373 3374 if (data->pcie_lane_performance.max < 3375 ps->performance_levels[i].pcie_lane) 3376 data->pcie_lane_performance.max = 3377 ps->performance_levels[i].pcie_lane; 3378 if (data->pcie_lane_performance.min > 3379 ps->performance_levels[i].pcie_lane) 3380 data->pcie_lane_performance.min = 3381 ps->performance_levels[i].pcie_lane; 3382 } 3383 break; 3384 case PP_StateUILabel_Battery: 3385 data->use_pcie_power_saving_levels = true; 3386 3387 for (i = 0; i < ps->performance_level_count; i++) { 3388 if (data->pcie_gen_power_saving.max < 3389 ps->performance_levels[i].pcie_gen) 3390 data->pcie_gen_power_saving.max = 3391 ps->performance_levels[i].pcie_gen; 3392 3393 if (data->pcie_gen_power_saving.min > 3394 ps->performance_levels[i].pcie_gen) 3395 data->pcie_gen_power_saving.min = 3396 ps->performance_levels[i].pcie_gen; 3397 3398 if (data->pcie_lane_power_saving.max < 3399 ps->performance_levels[i].pcie_lane) 3400 data->pcie_lane_power_saving.max = 3401 ps->performance_levels[i].pcie_lane; 3402 3403 if (data->pcie_lane_power_saving.min > 3404 ps->performance_levels[i].pcie_lane) 3405 data->pcie_lane_power_saving.min = 3406 ps->performance_levels[i].pcie_lane; 3407 } 3408 break; 3409 default: 3410 break; 3411 } 3412 } 3413 return 0; 3414 } 3415 3416 static int smu7_get_pp_table_entry_callback_func_v0(struct pp_hwmgr *hwmgr, 3417 struct pp_hw_power_state *power_state, 3418 unsigned int index, const void *clock_info) 3419 { 3420 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 3421 struct smu7_power_state *ps = cast_phw_smu7_power_state(power_state); 3422 const ATOM_PPLIB_CI_CLOCK_INFO *visland_clk_info = clock_info; 3423 struct smu7_performance_level *performance_level; 3424 uint32_t engine_clock, memory_clock; 3425 uint16_t pcie_gen_from_bios; 3426 3427 engine_clock = visland_clk_info->ucEngineClockHigh << 16 | visland_clk_info->usEngineClockLow; 3428 memory_clock = visland_clk_info->ucMemoryClockHigh << 16 | visland_clk_info->usMemoryClockLow; 3429 3430 if (!(data->mc_micro_code_feature & DISABLE_MC_LOADMICROCODE) && memory_clock > data->highest_mclk) 3431 data->highest_mclk = memory_clock; 3432 3433 PP_ASSERT_WITH_CODE( 3434 (ps->performance_level_count < smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_GRAPHICS)), 3435 "Performance levels exceeds SMC limit!", 3436 return -EINVAL); 3437 3438 PP_ASSERT_WITH_CODE( 3439 (ps->performance_level_count < 3440 hwmgr->platform_descriptor.hardwareActivityPerformanceLevels), 3441 "Performance levels exceeds Driver limit, Skip!", 3442 return 0); 3443 3444 performance_level = &(ps->performance_levels 3445 [ps->performance_level_count++]); 3446 3447 /* Performance levels are arranged from low to high. */ 3448 performance_level->memory_clock = memory_clock; 3449 performance_level->engine_clock = engine_clock; 3450 3451 pcie_gen_from_bios = visland_clk_info->ucPCIEGen; 3452 3453 performance_level->pcie_gen = get_pcie_gen_support(data->pcie_gen_cap, pcie_gen_from_bios); 3454 performance_level->pcie_lane = get_pcie_lane_support(data->pcie_lane_cap, visland_clk_info->usPCIELane); 3455 3456 return 0; 3457 } 3458 3459 static int smu7_get_pp_table_entry_v0(struct pp_hwmgr *hwmgr, 3460 unsigned long entry_index, struct pp_power_state *state) 3461 { 3462 int result; 3463 struct smu7_power_state *ps; 3464 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 3465 struct phm_clock_voltage_dependency_table *dep_mclk_table = 3466 hwmgr->dyn_state.vddci_dependency_on_mclk; 3467 3468 memset(&state->hardware, 0x00, sizeof(struct pp_hw_power_state)); 3469 3470 state->hardware.magic = PHM_VIslands_Magic; 3471 3472 ps = (struct smu7_power_state *)(&state->hardware); 3473 3474 result = pp_tables_get_entry(hwmgr, entry_index, state, 3475 smu7_get_pp_table_entry_callback_func_v0); 3476 3477 /* 3478 * This is the earliest time we have all the dependency table 3479 * and the VBIOS boot state as 3480 * PP_Tables_GetPowerPlayTableEntry retrieves the VBIOS boot 3481 * state if there is only one VDDCI/MCLK level, check if it's 3482 * the same as VBIOS boot state 3483 */ 3484 if (dep_mclk_table != NULL && dep_mclk_table->count == 1) { 3485 if (dep_mclk_table->entries[0].clk != 3486 data->vbios_boot_state.mclk_bootup_value) 3487 pr_debug("Single MCLK entry VDDCI/MCLK dependency table " 3488 "does not match VBIOS boot MCLK level"); 3489 if (dep_mclk_table->entries[0].v != 3490 data->vbios_boot_state.vddci_bootup_value) 3491 pr_debug("Single VDDCI entry VDDCI/MCLK dependency table " 3492 "does not match VBIOS boot VDDCI level"); 3493 } 3494 3495 /* set DC compatible flag if this state supports DC */ 3496 if (!state->validation.disallowOnDC) 3497 ps->dc_compatible = true; 3498 3499 if (state->classification.flags & PP_StateClassificationFlag_ACPI) 3500 data->acpi_pcie_gen = ps->performance_levels[0].pcie_gen; 3501 3502 ps->uvd_clks.vclk = state->uvd_clocks.VCLK; 3503 ps->uvd_clks.dclk = state->uvd_clocks.DCLK; 3504 3505 if (!result) { 3506 uint32_t i; 3507 3508 switch (state->classification.ui_label) { 3509 case PP_StateUILabel_Performance: 3510 data->use_pcie_performance_levels = true; 3511 3512 for (i = 0; i < ps->performance_level_count; i++) { 3513 if (data->pcie_gen_performance.max < 3514 ps->performance_levels[i].pcie_gen) 3515 data->pcie_gen_performance.max = 3516 ps->performance_levels[i].pcie_gen; 3517 3518 if (data->pcie_gen_performance.min > 3519 ps->performance_levels[i].pcie_gen) 3520 data->pcie_gen_performance.min = 3521 ps->performance_levels[i].pcie_gen; 3522 3523 if (data->pcie_lane_performance.max < 3524 ps->performance_levels[i].pcie_lane) 3525 data->pcie_lane_performance.max = 3526 ps->performance_levels[i].pcie_lane; 3527 3528 if (data->pcie_lane_performance.min > 3529 ps->performance_levels[i].pcie_lane) 3530 data->pcie_lane_performance.min = 3531 ps->performance_levels[i].pcie_lane; 3532 } 3533 break; 3534 case PP_StateUILabel_Battery: 3535 data->use_pcie_power_saving_levels = true; 3536 3537 for (i = 0; i < ps->performance_level_count; i++) { 3538 if (data->pcie_gen_power_saving.max < 3539 ps->performance_levels[i].pcie_gen) 3540 data->pcie_gen_power_saving.max = 3541 ps->performance_levels[i].pcie_gen; 3542 3543 if (data->pcie_gen_power_saving.min > 3544 ps->performance_levels[i].pcie_gen) 3545 data->pcie_gen_power_saving.min = 3546 ps->performance_levels[i].pcie_gen; 3547 3548 if (data->pcie_lane_power_saving.max < 3549 ps->performance_levels[i].pcie_lane) 3550 data->pcie_lane_power_saving.max = 3551 ps->performance_levels[i].pcie_lane; 3552 3553 if (data->pcie_lane_power_saving.min > 3554 ps->performance_levels[i].pcie_lane) 3555 data->pcie_lane_power_saving.min = 3556 ps->performance_levels[i].pcie_lane; 3557 } 3558 break; 3559 default: 3560 break; 3561 } 3562 } 3563 return 0; 3564 } 3565 3566 static int smu7_get_pp_table_entry(struct pp_hwmgr *hwmgr, 3567 unsigned long entry_index, struct pp_power_state *state) 3568 { 3569 if (hwmgr->pp_table_version == PP_TABLE_V0) 3570 return smu7_get_pp_table_entry_v0(hwmgr, entry_index, state); 3571 else if (hwmgr->pp_table_version == PP_TABLE_V1) 3572 return smu7_get_pp_table_entry_v1(hwmgr, entry_index, state); 3573 3574 return 0; 3575 } 3576 3577 static int smu7_get_gpu_power(struct pp_hwmgr *hwmgr, u32 *query) 3578 { 3579 struct amdgpu_device *adev = hwmgr->adev; 3580 int i; 3581 u32 tmp = 0; 3582 3583 if (!query) 3584 return -EINVAL; 3585 3586 /* 3587 * PPSMC_MSG_GetCurrPkgPwr is not supported on: 3588 * - Hawaii 3589 * - Bonaire 3590 * - Fiji 3591 * - Tonga 3592 */ 3593 if ((adev->asic_type != CHIP_HAWAII) && 3594 (adev->asic_type != CHIP_BONAIRE) && 3595 (adev->asic_type != CHIP_FIJI) && 3596 (adev->asic_type != CHIP_TONGA)) { 3597 smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_GetCurrPkgPwr, 0, &tmp); 3598 *query = tmp; 3599 3600 if (tmp != 0) 3601 return 0; 3602 } 3603 3604 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_PmStatusLogStart, NULL); 3605 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 3606 ixSMU_PM_STATUS_95, 0); 3607 3608 for (i = 0; i < 10; i++) { 3609 drm_msleep(500); 3610 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_PmStatusLogSample, NULL); 3611 tmp = cgs_read_ind_register(hwmgr->device, 3612 CGS_IND_REG__SMC, 3613 ixSMU_PM_STATUS_95); 3614 if (tmp != 0) 3615 break; 3616 } 3617 *query = tmp; 3618 3619 return 0; 3620 } 3621 3622 static int smu7_read_sensor(struct pp_hwmgr *hwmgr, int idx, 3623 void *value, int *size) 3624 { 3625 uint32_t sclk, mclk, activity_percent; 3626 uint32_t offset, val_vid; 3627 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 3628 3629 /* size must be at least 4 bytes for all sensors */ 3630 if (*size < 4) 3631 return -EINVAL; 3632 3633 switch (idx) { 3634 case AMDGPU_PP_SENSOR_GFX_SCLK: 3635 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_API_GetSclkFrequency, &sclk); 3636 *((uint32_t *)value) = sclk; 3637 *size = 4; 3638 return 0; 3639 case AMDGPU_PP_SENSOR_GFX_MCLK: 3640 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_API_GetMclkFrequency, &mclk); 3641 *((uint32_t *)value) = mclk; 3642 *size = 4; 3643 return 0; 3644 case AMDGPU_PP_SENSOR_GPU_LOAD: 3645 case AMDGPU_PP_SENSOR_MEM_LOAD: 3646 offset = data->soft_regs_start + smum_get_offsetof(hwmgr, 3647 SMU_SoftRegisters, 3648 (idx == AMDGPU_PP_SENSOR_GPU_LOAD) ? 3649 AverageGraphicsActivity: 3650 AverageMemoryActivity); 3651 3652 activity_percent = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset); 3653 activity_percent += 0x80; 3654 activity_percent >>= 8; 3655 *((uint32_t *)value) = activity_percent > 100 ? 100 : activity_percent; 3656 *size = 4; 3657 return 0; 3658 case AMDGPU_PP_SENSOR_GPU_TEMP: 3659 *((uint32_t *)value) = smu7_thermal_get_temperature(hwmgr); 3660 *size = 4; 3661 return 0; 3662 case AMDGPU_PP_SENSOR_UVD_POWER: 3663 *((uint32_t *)value) = data->uvd_power_gated ? 0 : 1; 3664 *size = 4; 3665 return 0; 3666 case AMDGPU_PP_SENSOR_VCE_POWER: 3667 *((uint32_t *)value) = data->vce_power_gated ? 0 : 1; 3668 *size = 4; 3669 return 0; 3670 case AMDGPU_PP_SENSOR_GPU_POWER: 3671 return smu7_get_gpu_power(hwmgr, (uint32_t *)value); 3672 case AMDGPU_PP_SENSOR_VDDGFX: 3673 if ((data->vr_config & VRCONF_VDDGFX_MASK) == 3674 (VR_SVI2_PLANE_2 << VRCONF_VDDGFX_SHIFT)) 3675 val_vid = PHM_READ_INDIRECT_FIELD(hwmgr->device, 3676 CGS_IND_REG__SMC, PWR_SVI2_STATUS, PLANE2_VID); 3677 else 3678 val_vid = PHM_READ_INDIRECT_FIELD(hwmgr->device, 3679 CGS_IND_REG__SMC, PWR_SVI2_STATUS, PLANE1_VID); 3680 3681 *((uint32_t *)value) = (uint32_t)convert_to_vddc(val_vid); 3682 return 0; 3683 default: 3684 return -EINVAL; 3685 } 3686 } 3687 3688 static int smu7_find_dpm_states_clocks_in_dpm_table(struct pp_hwmgr *hwmgr, const void *input) 3689 { 3690 const struct phm_set_power_state_input *states = 3691 (const struct phm_set_power_state_input *)input; 3692 const struct smu7_power_state *smu7_ps = 3693 cast_const_phw_smu7_power_state(states->pnew_state); 3694 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 3695 struct smu7_single_dpm_table *sclk_table = &(data->dpm_table.sclk_table); 3696 uint32_t sclk = smu7_ps->performance_levels 3697 [smu7_ps->performance_level_count - 1].engine_clock; 3698 struct smu7_single_dpm_table *mclk_table = &(data->dpm_table.mclk_table); 3699 uint32_t mclk = smu7_ps->performance_levels 3700 [smu7_ps->performance_level_count - 1].memory_clock; 3701 struct PP_Clocks min_clocks = {0}; 3702 uint32_t i; 3703 3704 for (i = 0; i < sclk_table->count; i++) { 3705 if (sclk == sclk_table->dpm_levels[i].value) 3706 break; 3707 } 3708 3709 if (i >= sclk_table->count) { 3710 if (sclk > sclk_table->dpm_levels[i-1].value) { 3711 data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_SCLK; 3712 sclk_table->dpm_levels[i-1].value = sclk; 3713 } 3714 } else { 3715 /* TODO: Check SCLK in DAL's minimum clocks 3716 * in case DeepSleep divider update is required. 3717 */ 3718 if (data->display_timing.min_clock_in_sr != min_clocks.engineClockInSR && 3719 (min_clocks.engineClockInSR >= SMU7_MINIMUM_ENGINE_CLOCK || 3720 data->display_timing.min_clock_in_sr >= SMU7_MINIMUM_ENGINE_CLOCK)) 3721 data->need_update_smu7_dpm_table |= DPMTABLE_UPDATE_SCLK; 3722 } 3723 3724 for (i = 0; i < mclk_table->count; i++) { 3725 if (mclk == mclk_table->dpm_levels[i].value) 3726 break; 3727 } 3728 3729 if (i >= mclk_table->count) { 3730 if (mclk > mclk_table->dpm_levels[i-1].value) { 3731 data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_MCLK; 3732 mclk_table->dpm_levels[i-1].value = mclk; 3733 } 3734 } 3735 3736 if (data->display_timing.num_existing_displays != hwmgr->display_config->num_display) 3737 data->need_update_smu7_dpm_table |= DPMTABLE_UPDATE_MCLK; 3738 3739 return 0; 3740 } 3741 3742 static uint16_t smu7_get_maximum_link_speed(struct pp_hwmgr *hwmgr, 3743 const struct smu7_power_state *smu7_ps) 3744 { 3745 uint32_t i; 3746 uint32_t sclk, max_sclk = 0; 3747 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 3748 struct smu7_dpm_table *dpm_table = &data->dpm_table; 3749 3750 for (i = 0; i < smu7_ps->performance_level_count; i++) { 3751 sclk = smu7_ps->performance_levels[i].engine_clock; 3752 if (max_sclk < sclk) 3753 max_sclk = sclk; 3754 } 3755 3756 for (i = 0; i < dpm_table->sclk_table.count; i++) { 3757 if (dpm_table->sclk_table.dpm_levels[i].value == max_sclk) 3758 return (uint16_t) ((i >= dpm_table->pcie_speed_table.count) ? 3759 dpm_table->pcie_speed_table.dpm_levels 3760 [dpm_table->pcie_speed_table.count - 1].value : 3761 dpm_table->pcie_speed_table.dpm_levels[i].value); 3762 } 3763 3764 return 0; 3765 } 3766 3767 static int smu7_request_link_speed_change_before_state_change( 3768 struct pp_hwmgr *hwmgr, const void *input) 3769 { 3770 const struct phm_set_power_state_input *states = 3771 (const struct phm_set_power_state_input *)input; 3772 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 3773 const struct smu7_power_state *smu7_nps = 3774 cast_const_phw_smu7_power_state(states->pnew_state); 3775 const struct smu7_power_state *polaris10_cps = 3776 cast_const_phw_smu7_power_state(states->pcurrent_state); 3777 3778 uint16_t target_link_speed = smu7_get_maximum_link_speed(hwmgr, smu7_nps); 3779 uint16_t current_link_speed; 3780 3781 if (data->force_pcie_gen == PP_PCIEGenInvalid) 3782 current_link_speed = smu7_get_maximum_link_speed(hwmgr, polaris10_cps); 3783 else 3784 current_link_speed = data->force_pcie_gen; 3785 3786 data->force_pcie_gen = PP_PCIEGenInvalid; 3787 data->pspp_notify_required = false; 3788 3789 if (target_link_speed > current_link_speed) { 3790 switch (target_link_speed) { 3791 #ifdef CONFIG_ACPI 3792 case PP_PCIEGen3: 3793 if (0 == amdgpu_acpi_pcie_performance_request(hwmgr->adev, PCIE_PERF_REQ_GEN3, false)) 3794 break; 3795 data->force_pcie_gen = PP_PCIEGen2; 3796 if (current_link_speed == PP_PCIEGen2) 3797 break; 3798 fallthrough; 3799 case PP_PCIEGen2: 3800 if (0 == amdgpu_acpi_pcie_performance_request(hwmgr->adev, PCIE_PERF_REQ_GEN2, false)) 3801 break; 3802 fallthrough; 3803 #endif 3804 default: 3805 data->force_pcie_gen = smu7_get_current_pcie_speed(hwmgr); 3806 break; 3807 } 3808 } else { 3809 if (target_link_speed < current_link_speed) 3810 data->pspp_notify_required = true; 3811 } 3812 3813 return 0; 3814 } 3815 3816 static int smu7_freeze_sclk_mclk_dpm(struct pp_hwmgr *hwmgr) 3817 { 3818 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 3819 3820 if (0 == data->need_update_smu7_dpm_table) 3821 return 0; 3822 3823 if ((0 == data->sclk_dpm_key_disabled) && 3824 (data->need_update_smu7_dpm_table & 3825 (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_UPDATE_SCLK))) { 3826 PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr), 3827 "Trying to freeze SCLK DPM when DPM is disabled", 3828 ); 3829 PP_ASSERT_WITH_CODE(0 == smum_send_msg_to_smc(hwmgr, 3830 PPSMC_MSG_SCLKDPM_FreezeLevel, 3831 NULL), 3832 "Failed to freeze SCLK DPM during FreezeSclkMclkDPM Function!", 3833 return -EINVAL); 3834 } 3835 3836 if ((0 == data->mclk_dpm_key_disabled) && 3837 (data->need_update_smu7_dpm_table & 3838 DPMTABLE_OD_UPDATE_MCLK)) { 3839 PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr), 3840 "Trying to freeze MCLK DPM when DPM is disabled", 3841 ); 3842 PP_ASSERT_WITH_CODE(0 == smum_send_msg_to_smc(hwmgr, 3843 PPSMC_MSG_MCLKDPM_FreezeLevel, 3844 NULL), 3845 "Failed to freeze MCLK DPM during FreezeSclkMclkDPM Function!", 3846 return -EINVAL); 3847 } 3848 3849 return 0; 3850 } 3851 3852 static int smu7_populate_and_upload_sclk_mclk_dpm_levels( 3853 struct pp_hwmgr *hwmgr, const void *input) 3854 { 3855 int result = 0; 3856 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 3857 struct smu7_dpm_table *dpm_table = &data->dpm_table; 3858 uint32_t count; 3859 struct smu7_odn_dpm_table *odn_table = &(data->odn_dpm_table); 3860 struct phm_odn_clock_levels *odn_sclk_table = &(odn_table->odn_core_clock_dpm_levels); 3861 struct phm_odn_clock_levels *odn_mclk_table = &(odn_table->odn_memory_clock_dpm_levels); 3862 3863 if (0 == data->need_update_smu7_dpm_table) 3864 return 0; 3865 3866 if (hwmgr->od_enabled && data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_SCLK) { 3867 for (count = 0; count < dpm_table->sclk_table.count; count++) { 3868 dpm_table->sclk_table.dpm_levels[count].enabled = odn_sclk_table->entries[count].enabled; 3869 dpm_table->sclk_table.dpm_levels[count].value = odn_sclk_table->entries[count].clock; 3870 } 3871 } 3872 3873 if (hwmgr->od_enabled && data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_MCLK) { 3874 for (count = 0; count < dpm_table->mclk_table.count; count++) { 3875 dpm_table->mclk_table.dpm_levels[count].enabled = odn_mclk_table->entries[count].enabled; 3876 dpm_table->mclk_table.dpm_levels[count].value = odn_mclk_table->entries[count].clock; 3877 } 3878 } 3879 3880 if (data->need_update_smu7_dpm_table & 3881 (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_UPDATE_SCLK)) { 3882 result = smum_populate_all_graphic_levels(hwmgr); 3883 PP_ASSERT_WITH_CODE((0 == result), 3884 "Failed to populate SCLK during PopulateNewDPMClocksStates Function!", 3885 return result); 3886 } 3887 3888 if (data->need_update_smu7_dpm_table & 3889 (DPMTABLE_OD_UPDATE_MCLK + DPMTABLE_UPDATE_MCLK)) { 3890 /*populate MCLK dpm table to SMU7 */ 3891 result = smum_populate_all_memory_levels(hwmgr); 3892 PP_ASSERT_WITH_CODE((0 == result), 3893 "Failed to populate MCLK during PopulateNewDPMClocksStates Function!", 3894 return result); 3895 } 3896 3897 return result; 3898 } 3899 3900 static int smu7_trim_single_dpm_states(struct pp_hwmgr *hwmgr, 3901 struct smu7_single_dpm_table *dpm_table, 3902 uint32_t low_limit, uint32_t high_limit) 3903 { 3904 uint32_t i; 3905 3906 /* force the trim if mclk_switching is disabled to prevent flicker */ 3907 bool force_trim = (low_limit == high_limit); 3908 for (i = 0; i < dpm_table->count; i++) { 3909 /*skip the trim if od is enabled*/ 3910 if ((!hwmgr->od_enabled || force_trim) 3911 && (dpm_table->dpm_levels[i].value < low_limit 3912 || dpm_table->dpm_levels[i].value > high_limit)) 3913 dpm_table->dpm_levels[i].enabled = false; 3914 else 3915 dpm_table->dpm_levels[i].enabled = true; 3916 } 3917 3918 return 0; 3919 } 3920 3921 static int smu7_trim_dpm_states(struct pp_hwmgr *hwmgr, 3922 const struct smu7_power_state *smu7_ps) 3923 { 3924 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 3925 uint32_t high_limit_count; 3926 3927 PP_ASSERT_WITH_CODE((smu7_ps->performance_level_count >= 1), 3928 "power state did not have any performance level", 3929 return -EINVAL); 3930 3931 high_limit_count = (1 == smu7_ps->performance_level_count) ? 0 : 1; 3932 3933 smu7_trim_single_dpm_states(hwmgr, 3934 &(data->dpm_table.sclk_table), 3935 smu7_ps->performance_levels[0].engine_clock, 3936 smu7_ps->performance_levels[high_limit_count].engine_clock); 3937 3938 smu7_trim_single_dpm_states(hwmgr, 3939 &(data->dpm_table.mclk_table), 3940 smu7_ps->performance_levels[0].memory_clock, 3941 smu7_ps->performance_levels[high_limit_count].memory_clock); 3942 3943 return 0; 3944 } 3945 3946 static int smu7_generate_dpm_level_enable_mask( 3947 struct pp_hwmgr *hwmgr, const void *input) 3948 { 3949 int result = 0; 3950 const struct phm_set_power_state_input *states = 3951 (const struct phm_set_power_state_input *)input; 3952 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 3953 const struct smu7_power_state *smu7_ps = 3954 cast_const_phw_smu7_power_state(states->pnew_state); 3955 3956 3957 result = smu7_trim_dpm_states(hwmgr, smu7_ps); 3958 if (result) 3959 return result; 3960 3961 data->dpm_level_enable_mask.sclk_dpm_enable_mask = 3962 phm_get_dpm_level_enable_mask_value(&data->dpm_table.sclk_table); 3963 data->dpm_level_enable_mask.mclk_dpm_enable_mask = 3964 phm_get_dpm_level_enable_mask_value(&data->dpm_table.mclk_table); 3965 data->dpm_level_enable_mask.pcie_dpm_enable_mask = 3966 phm_get_dpm_level_enable_mask_value(&data->dpm_table.pcie_speed_table); 3967 3968 return 0; 3969 } 3970 3971 static int smu7_unfreeze_sclk_mclk_dpm(struct pp_hwmgr *hwmgr) 3972 { 3973 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 3974 3975 if (0 == data->need_update_smu7_dpm_table) 3976 return 0; 3977 3978 if ((0 == data->sclk_dpm_key_disabled) && 3979 (data->need_update_smu7_dpm_table & 3980 (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_UPDATE_SCLK))) { 3981 3982 PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr), 3983 "Trying to Unfreeze SCLK DPM when DPM is disabled", 3984 ); 3985 PP_ASSERT_WITH_CODE(0 == smum_send_msg_to_smc(hwmgr, 3986 PPSMC_MSG_SCLKDPM_UnfreezeLevel, 3987 NULL), 3988 "Failed to unfreeze SCLK DPM during UnFreezeSclkMclkDPM Function!", 3989 return -EINVAL); 3990 } 3991 3992 if ((0 == data->mclk_dpm_key_disabled) && 3993 (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_MCLK)) { 3994 3995 PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr), 3996 "Trying to Unfreeze MCLK DPM when DPM is disabled", 3997 ); 3998 PP_ASSERT_WITH_CODE(0 == smum_send_msg_to_smc(hwmgr, 3999 PPSMC_MSG_MCLKDPM_UnfreezeLevel, 4000 NULL), 4001 "Failed to unfreeze MCLK DPM during UnFreezeSclkMclkDPM Function!", 4002 return -EINVAL); 4003 } 4004 4005 data->need_update_smu7_dpm_table &= DPMTABLE_OD_UPDATE_VDDC; 4006 4007 return 0; 4008 } 4009 4010 static int smu7_notify_link_speed_change_after_state_change( 4011 struct pp_hwmgr *hwmgr, const void *input) 4012 { 4013 const struct phm_set_power_state_input *states = 4014 (const struct phm_set_power_state_input *)input; 4015 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 4016 const struct smu7_power_state *smu7_ps = 4017 cast_const_phw_smu7_power_state(states->pnew_state); 4018 uint16_t target_link_speed = smu7_get_maximum_link_speed(hwmgr, smu7_ps); 4019 uint8_t request; 4020 4021 if (data->pspp_notify_required) { 4022 if (target_link_speed == PP_PCIEGen3) 4023 request = PCIE_PERF_REQ_GEN3; 4024 else if (target_link_speed == PP_PCIEGen2) 4025 request = PCIE_PERF_REQ_GEN2; 4026 else 4027 request = PCIE_PERF_REQ_GEN1; 4028 4029 if (request == PCIE_PERF_REQ_GEN1 && 4030 smu7_get_current_pcie_speed(hwmgr) > 0) 4031 return 0; 4032 4033 #ifdef CONFIG_ACPI 4034 if (amdgpu_acpi_pcie_performance_request(hwmgr->adev, request, false)) { 4035 if (PP_PCIEGen2 == target_link_speed) 4036 pr_info("PSPP request to switch to Gen2 from Gen3 Failed!"); 4037 else 4038 pr_info("PSPP request to switch to Gen1 from Gen2 Failed!"); 4039 } 4040 #endif 4041 } 4042 4043 return 0; 4044 } 4045 4046 static int smu7_notify_smc_display(struct pp_hwmgr *hwmgr) 4047 { 4048 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 4049 4050 if (hwmgr->feature_mask & PP_VBI_TIME_SUPPORT_MASK) { 4051 if (hwmgr->chip_id == CHIP_VEGAM) 4052 smum_send_msg_to_smc_with_parameter(hwmgr, 4053 (PPSMC_Msg)PPSMC_MSG_SetVBITimeout_VEGAM, data->frame_time_x2, 4054 NULL); 4055 else 4056 smum_send_msg_to_smc_with_parameter(hwmgr, 4057 (PPSMC_Msg)PPSMC_MSG_SetVBITimeout, data->frame_time_x2, 4058 NULL); 4059 } 4060 return (smum_send_msg_to_smc(hwmgr, (PPSMC_Msg)PPSMC_HasDisplay, NULL) == 0) ? 0 : -EINVAL; 4061 } 4062 4063 static int smu7_set_power_state_tasks(struct pp_hwmgr *hwmgr, const void *input) 4064 { 4065 int tmp_result, result = 0; 4066 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 4067 4068 tmp_result = smu7_find_dpm_states_clocks_in_dpm_table(hwmgr, input); 4069 PP_ASSERT_WITH_CODE((0 == tmp_result), 4070 "Failed to find DPM states clocks in DPM table!", 4071 result = tmp_result); 4072 4073 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, 4074 PHM_PlatformCaps_PCIEPerformanceRequest)) { 4075 tmp_result = 4076 smu7_request_link_speed_change_before_state_change(hwmgr, input); 4077 PP_ASSERT_WITH_CODE((0 == tmp_result), 4078 "Failed to request link speed change before state change!", 4079 result = tmp_result); 4080 } 4081 4082 tmp_result = smu7_freeze_sclk_mclk_dpm(hwmgr); 4083 PP_ASSERT_WITH_CODE((0 == tmp_result), 4084 "Failed to freeze SCLK MCLK DPM!", result = tmp_result); 4085 4086 tmp_result = smu7_populate_and_upload_sclk_mclk_dpm_levels(hwmgr, input); 4087 PP_ASSERT_WITH_CODE((0 == tmp_result), 4088 "Failed to populate and upload SCLK MCLK DPM levels!", 4089 result = tmp_result); 4090 4091 /* 4092 * If a custom pp table is loaded, set DPMTABLE_OD_UPDATE_VDDC flag. 4093 * That effectively disables AVFS feature. 4094 */ 4095 if (hwmgr->hardcode_pp_table != NULL) 4096 data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_VDDC; 4097 4098 tmp_result = smu7_update_avfs(hwmgr); 4099 PP_ASSERT_WITH_CODE((0 == tmp_result), 4100 "Failed to update avfs voltages!", 4101 result = tmp_result); 4102 4103 tmp_result = smu7_generate_dpm_level_enable_mask(hwmgr, input); 4104 PP_ASSERT_WITH_CODE((0 == tmp_result), 4105 "Failed to generate DPM level enabled mask!", 4106 result = tmp_result); 4107 4108 tmp_result = smum_update_sclk_threshold(hwmgr); 4109 PP_ASSERT_WITH_CODE((0 == tmp_result), 4110 "Failed to update SCLK threshold!", 4111 result = tmp_result); 4112 4113 tmp_result = smu7_notify_smc_display(hwmgr); 4114 PP_ASSERT_WITH_CODE((0 == tmp_result), 4115 "Failed to notify smc display settings!", 4116 result = tmp_result); 4117 4118 tmp_result = smu7_unfreeze_sclk_mclk_dpm(hwmgr); 4119 PP_ASSERT_WITH_CODE((0 == tmp_result), 4120 "Failed to unfreeze SCLK MCLK DPM!", 4121 result = tmp_result); 4122 4123 tmp_result = smu7_upload_dpm_level_enable_mask(hwmgr); 4124 PP_ASSERT_WITH_CODE((0 == tmp_result), 4125 "Failed to upload DPM level enabled mask!", 4126 result = tmp_result); 4127 4128 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, 4129 PHM_PlatformCaps_PCIEPerformanceRequest)) { 4130 tmp_result = 4131 smu7_notify_link_speed_change_after_state_change(hwmgr, input); 4132 PP_ASSERT_WITH_CODE((0 == tmp_result), 4133 "Failed to notify link speed change after state change!", 4134 result = tmp_result); 4135 } 4136 data->apply_optimized_settings = false; 4137 return result; 4138 } 4139 4140 static int smu7_set_max_fan_pwm_output(struct pp_hwmgr *hwmgr, uint16_t us_max_fan_pwm) 4141 { 4142 hwmgr->thermal_controller. 4143 advanceFanControlParameters.usMaxFanPWM = us_max_fan_pwm; 4144 4145 return smum_send_msg_to_smc_with_parameter(hwmgr, 4146 PPSMC_MSG_SetFanPwmMax, us_max_fan_pwm, 4147 NULL); 4148 } 4149 4150 static int 4151 smu7_notify_smc_display_change(struct pp_hwmgr *hwmgr, bool has_display) 4152 { 4153 PPSMC_Msg msg = has_display ? (PPSMC_Msg)PPSMC_HasDisplay : (PPSMC_Msg)PPSMC_NoDisplay; 4154 4155 return (smum_send_msg_to_smc(hwmgr, msg, NULL) == 0) ? 0 : -1; 4156 } 4157 4158 static int 4159 smu7_notify_smc_display_config_after_ps_adjustment(struct pp_hwmgr *hwmgr) 4160 { 4161 if (hwmgr->display_config->num_display > 1 && 4162 !hwmgr->display_config->multi_monitor_in_sync) 4163 smu7_notify_smc_display_change(hwmgr, false); 4164 4165 return 0; 4166 } 4167 4168 /** 4169 * Programs the display gap 4170 * 4171 * @param hwmgr the address of the powerplay hardware manager. 4172 * @return always OK 4173 */ 4174 static int smu7_program_display_gap(struct pp_hwmgr *hwmgr) 4175 { 4176 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 4177 uint32_t display_gap = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_DISPLAY_GAP_CNTL); 4178 uint32_t display_gap2; 4179 uint32_t pre_vbi_time_in_us; 4180 uint32_t frame_time_in_us; 4181 uint32_t ref_clock, refresh_rate; 4182 4183 display_gap = PHM_SET_FIELD(display_gap, CG_DISPLAY_GAP_CNTL, DISP_GAP, (hwmgr->display_config->num_display > 0) ? DISPLAY_GAP_VBLANK_OR_WM : DISPLAY_GAP_IGNORE); 4184 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_DISPLAY_GAP_CNTL, display_gap); 4185 4186 ref_clock = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev); 4187 refresh_rate = hwmgr->display_config->vrefresh; 4188 4189 if (0 == refresh_rate) 4190 refresh_rate = 60; 4191 4192 frame_time_in_us = 1000000 / refresh_rate; 4193 4194 pre_vbi_time_in_us = frame_time_in_us - 200 - hwmgr->display_config->min_vblank_time; 4195 4196 data->frame_time_x2 = frame_time_in_us * 2 / 100; 4197 4198 if (data->frame_time_x2 < 280) { 4199 pr_debug("%s: enforce minimal VBITimeout: %d -> 280\n", __func__, data->frame_time_x2); 4200 data->frame_time_x2 = 280; 4201 } 4202 4203 display_gap2 = pre_vbi_time_in_us * (ref_clock / 100); 4204 4205 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_DISPLAY_GAP_CNTL2, display_gap2); 4206 4207 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 4208 data->soft_regs_start + smum_get_offsetof(hwmgr, 4209 SMU_SoftRegisters, 4210 PreVBlankGap), 0x64); 4211 4212 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 4213 data->soft_regs_start + smum_get_offsetof(hwmgr, 4214 SMU_SoftRegisters, 4215 VBlankTimeout), 4216 (frame_time_in_us - pre_vbi_time_in_us)); 4217 4218 return 0; 4219 } 4220 4221 static int smu7_display_configuration_changed_task(struct pp_hwmgr *hwmgr) 4222 { 4223 return smu7_program_display_gap(hwmgr); 4224 } 4225 4226 /** 4227 * Set maximum target operating fan output RPM 4228 * 4229 * @param hwmgr: the address of the powerplay hardware manager. 4230 * @param usMaxFanRpm: max operating fan RPM value. 4231 * @return The response that came from the SMC. 4232 */ 4233 static int smu7_set_max_fan_rpm_output(struct pp_hwmgr *hwmgr, uint16_t us_max_fan_rpm) 4234 { 4235 hwmgr->thermal_controller. 4236 advanceFanControlParameters.usMaxFanRPM = us_max_fan_rpm; 4237 4238 return smum_send_msg_to_smc_with_parameter(hwmgr, 4239 PPSMC_MSG_SetFanRpmMax, us_max_fan_rpm, 4240 NULL); 4241 } 4242 4243 static const struct amdgpu_irq_src_funcs smu7_irq_funcs = { 4244 .process = phm_irq_process, 4245 }; 4246 4247 static int smu7_register_irq_handlers(struct pp_hwmgr *hwmgr) 4248 { 4249 struct amdgpu_irq_src *source = 4250 kzalloc(sizeof(struct amdgpu_irq_src), GFP_KERNEL); 4251 4252 if (!source) 4253 return -ENOMEM; 4254 4255 source->funcs = &smu7_irq_funcs; 4256 4257 amdgpu_irq_add_id((struct amdgpu_device *)(hwmgr->adev), 4258 AMDGPU_IRQ_CLIENTID_LEGACY, 4259 VISLANDS30_IV_SRCID_CG_TSS_THERMAL_LOW_TO_HIGH, 4260 source); 4261 amdgpu_irq_add_id((struct amdgpu_device *)(hwmgr->adev), 4262 AMDGPU_IRQ_CLIENTID_LEGACY, 4263 VISLANDS30_IV_SRCID_CG_TSS_THERMAL_HIGH_TO_LOW, 4264 source); 4265 4266 /* Register CTF(GPIO_19) interrupt */ 4267 amdgpu_irq_add_id((struct amdgpu_device *)(hwmgr->adev), 4268 AMDGPU_IRQ_CLIENTID_LEGACY, 4269 VISLANDS30_IV_SRCID_GPIO_19, 4270 source); 4271 4272 return 0; 4273 } 4274 4275 static bool 4276 smu7_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr) 4277 { 4278 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 4279 bool is_update_required = false; 4280 4281 if (data->display_timing.num_existing_displays != hwmgr->display_config->num_display) 4282 is_update_required = true; 4283 4284 if (data->display_timing.vrefresh != hwmgr->display_config->vrefresh) 4285 is_update_required = true; 4286 4287 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep)) { 4288 if (data->display_timing.min_clock_in_sr != hwmgr->display_config->min_core_set_clock_in_sr && 4289 (data->display_timing.min_clock_in_sr >= SMU7_MINIMUM_ENGINE_CLOCK || 4290 hwmgr->display_config->min_core_set_clock_in_sr >= SMU7_MINIMUM_ENGINE_CLOCK)) 4291 is_update_required = true; 4292 } 4293 return is_update_required; 4294 } 4295 4296 static inline bool smu7_are_power_levels_equal(const struct smu7_performance_level *pl1, 4297 const struct smu7_performance_level *pl2) 4298 { 4299 return ((pl1->memory_clock == pl2->memory_clock) && 4300 (pl1->engine_clock == pl2->engine_clock) && 4301 (pl1->pcie_gen == pl2->pcie_gen) && 4302 (pl1->pcie_lane == pl2->pcie_lane)); 4303 } 4304 4305 static int smu7_check_states_equal(struct pp_hwmgr *hwmgr, 4306 const struct pp_hw_power_state *pstate1, 4307 const struct pp_hw_power_state *pstate2, bool *equal) 4308 { 4309 const struct smu7_power_state *psa; 4310 const struct smu7_power_state *psb; 4311 int i; 4312 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 4313 4314 if (pstate1 == NULL || pstate2 == NULL || equal == NULL) 4315 return -EINVAL; 4316 4317 psa = cast_const_phw_smu7_power_state(pstate1); 4318 psb = cast_const_phw_smu7_power_state(pstate2); 4319 /* If the two states don't even have the same number of performance levels they cannot be the same state. */ 4320 if (psa->performance_level_count != psb->performance_level_count) { 4321 *equal = false; 4322 return 0; 4323 } 4324 4325 for (i = 0; i < psa->performance_level_count; i++) { 4326 if (!smu7_are_power_levels_equal(&(psa->performance_levels[i]), &(psb->performance_levels[i]))) { 4327 /* If we have found even one performance level pair that is different the states are different. */ 4328 *equal = false; 4329 return 0; 4330 } 4331 } 4332 4333 /* If all performance levels are the same try to use the UVD clocks to break the tie.*/ 4334 *equal = ((psa->uvd_clks.vclk == psb->uvd_clks.vclk) && (psa->uvd_clks.dclk == psb->uvd_clks.dclk)); 4335 *equal &= ((psa->vce_clks.evclk == psb->vce_clks.evclk) && (psa->vce_clks.ecclk == psb->vce_clks.ecclk)); 4336 *equal &= (psa->sclk_threshold == psb->sclk_threshold); 4337 /* For OD call, set value based on flag */ 4338 *equal &= !(data->need_update_smu7_dpm_table & (DPMTABLE_OD_UPDATE_SCLK | 4339 DPMTABLE_OD_UPDATE_MCLK | 4340 DPMTABLE_OD_UPDATE_VDDC)); 4341 4342 return 0; 4343 } 4344 4345 static int smu7_check_mc_firmware(struct pp_hwmgr *hwmgr) 4346 { 4347 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 4348 4349 uint32_t tmp; 4350 4351 /* Read MC indirect register offset 0x9F bits [3:0] to see 4352 * if VBIOS has already loaded a full version of MC ucode 4353 * or not. 4354 */ 4355 4356 smu7_get_mc_microcode_version(hwmgr); 4357 4358 data->need_long_memory_training = false; 4359 4360 cgs_write_register(hwmgr->device, mmMC_SEQ_IO_DEBUG_INDEX, 4361 ixMC_IO_DEBUG_UP_13); 4362 tmp = cgs_read_register(hwmgr->device, mmMC_SEQ_IO_DEBUG_DATA); 4363 4364 if (tmp & (1 << 23)) { 4365 data->mem_latency_high = MEM_LATENCY_HIGH; 4366 data->mem_latency_low = MEM_LATENCY_LOW; 4367 if ((hwmgr->chip_id == CHIP_POLARIS10) || 4368 (hwmgr->chip_id == CHIP_POLARIS11) || 4369 (hwmgr->chip_id == CHIP_POLARIS12)) 4370 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_EnableFFC, NULL); 4371 } else { 4372 data->mem_latency_high = 330; 4373 data->mem_latency_low = 330; 4374 if ((hwmgr->chip_id == CHIP_POLARIS10) || 4375 (hwmgr->chip_id == CHIP_POLARIS11) || 4376 (hwmgr->chip_id == CHIP_POLARIS12)) 4377 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_DisableFFC, NULL); 4378 } 4379 4380 return 0; 4381 } 4382 4383 static int smu7_read_clock_registers(struct pp_hwmgr *hwmgr) 4384 { 4385 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 4386 4387 data->clock_registers.vCG_SPLL_FUNC_CNTL = 4388 cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_SPLL_FUNC_CNTL); 4389 data->clock_registers.vCG_SPLL_FUNC_CNTL_2 = 4390 cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_SPLL_FUNC_CNTL_2); 4391 data->clock_registers.vCG_SPLL_FUNC_CNTL_3 = 4392 cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_SPLL_FUNC_CNTL_3); 4393 data->clock_registers.vCG_SPLL_FUNC_CNTL_4 = 4394 cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_SPLL_FUNC_CNTL_4); 4395 data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM = 4396 cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_SPLL_SPREAD_SPECTRUM); 4397 data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2 = 4398 cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_SPLL_SPREAD_SPECTRUM_2); 4399 data->clock_registers.vDLL_CNTL = 4400 cgs_read_register(hwmgr->device, mmDLL_CNTL); 4401 data->clock_registers.vMCLK_PWRMGT_CNTL = 4402 cgs_read_register(hwmgr->device, mmMCLK_PWRMGT_CNTL); 4403 data->clock_registers.vMPLL_AD_FUNC_CNTL = 4404 cgs_read_register(hwmgr->device, mmMPLL_AD_FUNC_CNTL); 4405 data->clock_registers.vMPLL_DQ_FUNC_CNTL = 4406 cgs_read_register(hwmgr->device, mmMPLL_DQ_FUNC_CNTL); 4407 data->clock_registers.vMPLL_FUNC_CNTL = 4408 cgs_read_register(hwmgr->device, mmMPLL_FUNC_CNTL); 4409 data->clock_registers.vMPLL_FUNC_CNTL_1 = 4410 cgs_read_register(hwmgr->device, mmMPLL_FUNC_CNTL_1); 4411 data->clock_registers.vMPLL_FUNC_CNTL_2 = 4412 cgs_read_register(hwmgr->device, mmMPLL_FUNC_CNTL_2); 4413 data->clock_registers.vMPLL_SS1 = 4414 cgs_read_register(hwmgr->device, mmMPLL_SS1); 4415 data->clock_registers.vMPLL_SS2 = 4416 cgs_read_register(hwmgr->device, mmMPLL_SS2); 4417 return 0; 4418 4419 } 4420 4421 /** 4422 * Find out if memory is GDDR5. 4423 * 4424 * @param hwmgr the address of the powerplay hardware manager. 4425 * @return always 0 4426 */ 4427 static int smu7_get_memory_type(struct pp_hwmgr *hwmgr) 4428 { 4429 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 4430 struct amdgpu_device *adev = hwmgr->adev; 4431 4432 data->is_memory_gddr5 = (adev->gmc.vram_type == AMDGPU_VRAM_TYPE_GDDR5); 4433 4434 return 0; 4435 } 4436 4437 /** 4438 * Enables Dynamic Power Management by SMC 4439 * 4440 * @param hwmgr the address of the powerplay hardware manager. 4441 * @return always 0 4442 */ 4443 static int smu7_enable_acpi_power_management(struct pp_hwmgr *hwmgr) 4444 { 4445 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, 4446 GENERAL_PWRMGT, STATIC_PM_EN, 1); 4447 4448 return 0; 4449 } 4450 4451 /** 4452 * Initialize PowerGating States for different engines 4453 * 4454 * @param hwmgr the address of the powerplay hardware manager. 4455 * @return always 0 4456 */ 4457 static int smu7_init_power_gate_state(struct pp_hwmgr *hwmgr) 4458 { 4459 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 4460 4461 data->uvd_power_gated = false; 4462 data->vce_power_gated = false; 4463 4464 return 0; 4465 } 4466 4467 static int smu7_init_sclk_threshold(struct pp_hwmgr *hwmgr) 4468 { 4469 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 4470 4471 data->low_sclk_interrupt_threshold = 0; 4472 return 0; 4473 } 4474 4475 static int smu7_setup_asic_task(struct pp_hwmgr *hwmgr) 4476 { 4477 int tmp_result, result = 0; 4478 4479 smu7_check_mc_firmware(hwmgr); 4480 4481 tmp_result = smu7_read_clock_registers(hwmgr); 4482 PP_ASSERT_WITH_CODE((0 == tmp_result), 4483 "Failed to read clock registers!", result = tmp_result); 4484 4485 tmp_result = smu7_get_memory_type(hwmgr); 4486 PP_ASSERT_WITH_CODE((0 == tmp_result), 4487 "Failed to get memory type!", result = tmp_result); 4488 4489 tmp_result = smu7_enable_acpi_power_management(hwmgr); 4490 PP_ASSERT_WITH_CODE((0 == tmp_result), 4491 "Failed to enable ACPI power management!", result = tmp_result); 4492 4493 tmp_result = smu7_init_power_gate_state(hwmgr); 4494 PP_ASSERT_WITH_CODE((0 == tmp_result), 4495 "Failed to init power gate state!", result = tmp_result); 4496 4497 tmp_result = smu7_get_mc_microcode_version(hwmgr); 4498 PP_ASSERT_WITH_CODE((0 == tmp_result), 4499 "Failed to get MC microcode version!", result = tmp_result); 4500 4501 tmp_result = smu7_init_sclk_threshold(hwmgr); 4502 PP_ASSERT_WITH_CODE((0 == tmp_result), 4503 "Failed to init sclk threshold!", result = tmp_result); 4504 4505 return result; 4506 } 4507 4508 static int smu7_force_clock_level(struct pp_hwmgr *hwmgr, 4509 enum pp_clock_type type, uint32_t mask) 4510 { 4511 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 4512 4513 if (mask == 0) 4514 return -EINVAL; 4515 4516 switch (type) { 4517 case PP_SCLK: 4518 if (!data->sclk_dpm_key_disabled) 4519 smum_send_msg_to_smc_with_parameter(hwmgr, 4520 PPSMC_MSG_SCLKDPM_SetEnabledMask, 4521 data->dpm_level_enable_mask.sclk_dpm_enable_mask & mask, 4522 NULL); 4523 break; 4524 case PP_MCLK: 4525 if (!data->mclk_dpm_key_disabled) 4526 smum_send_msg_to_smc_with_parameter(hwmgr, 4527 PPSMC_MSG_MCLKDPM_SetEnabledMask, 4528 data->dpm_level_enable_mask.mclk_dpm_enable_mask & mask, 4529 NULL); 4530 break; 4531 case PP_PCIE: 4532 { 4533 uint32_t tmp = mask & data->dpm_level_enable_mask.pcie_dpm_enable_mask; 4534 4535 if (!data->pcie_dpm_key_disabled) { 4536 if (fls(tmp) != ffs(tmp)) 4537 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_PCIeDPM_UnForceLevel, 4538 NULL); 4539 else 4540 smum_send_msg_to_smc_with_parameter(hwmgr, 4541 PPSMC_MSG_PCIeDPM_ForceLevel, 4542 fls(tmp) - 1, 4543 NULL); 4544 } 4545 break; 4546 } 4547 default: 4548 break; 4549 } 4550 4551 return 0; 4552 } 4553 4554 static int smu7_print_clock_levels(struct pp_hwmgr *hwmgr, 4555 enum pp_clock_type type, char *buf) 4556 { 4557 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 4558 struct smu7_single_dpm_table *sclk_table = &(data->dpm_table.sclk_table); 4559 struct smu7_single_dpm_table *mclk_table = &(data->dpm_table.mclk_table); 4560 struct smu7_single_dpm_table *pcie_table = &(data->dpm_table.pcie_speed_table); 4561 struct smu7_odn_dpm_table *odn_table = &(data->odn_dpm_table); 4562 struct phm_odn_clock_levels *odn_sclk_table = &(odn_table->odn_core_clock_dpm_levels); 4563 struct phm_odn_clock_levels *odn_mclk_table = &(odn_table->odn_memory_clock_dpm_levels); 4564 int i, now, size = 0; 4565 uint32_t clock, pcie_speed; 4566 4567 switch (type) { 4568 case PP_SCLK: 4569 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_API_GetSclkFrequency, &clock); 4570 4571 for (i = 0; i < sclk_table->count; i++) { 4572 if (clock > sclk_table->dpm_levels[i].value) 4573 continue; 4574 break; 4575 } 4576 now = i; 4577 4578 for (i = 0; i < sclk_table->count; i++) 4579 size += snprintf(buf + size, PAGE_SIZE - size, "%d: %uMhz %s\n", 4580 i, sclk_table->dpm_levels[i].value / 100, 4581 (i == now) ? "*" : ""); 4582 break; 4583 case PP_MCLK: 4584 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_API_GetMclkFrequency, &clock); 4585 4586 for (i = 0; i < mclk_table->count; i++) { 4587 if (clock > mclk_table->dpm_levels[i].value) 4588 continue; 4589 break; 4590 } 4591 now = i; 4592 4593 for (i = 0; i < mclk_table->count; i++) 4594 size += snprintf(buf + size, PAGE_SIZE - size, "%d: %uMhz %s\n", 4595 i, mclk_table->dpm_levels[i].value / 100, 4596 (i == now) ? "*" : ""); 4597 break; 4598 case PP_PCIE: 4599 pcie_speed = smu7_get_current_pcie_speed(hwmgr); 4600 for (i = 0; i < pcie_table->count; i++) { 4601 if (pcie_speed != pcie_table->dpm_levels[i].value) 4602 continue; 4603 break; 4604 } 4605 now = i; 4606 4607 for (i = 0; i < pcie_table->count; i++) 4608 size += snprintf(buf + size, PAGE_SIZE - size, "%d: %s %s\n", i, 4609 (pcie_table->dpm_levels[i].value == 0) ? "2.5GT/s, x8" : 4610 (pcie_table->dpm_levels[i].value == 1) ? "5.0GT/s, x16" : 4611 (pcie_table->dpm_levels[i].value == 2) ? "8.0GT/s, x16" : "", 4612 (i == now) ? "*" : ""); 4613 break; 4614 case OD_SCLK: 4615 if (hwmgr->od_enabled) { 4616 size = snprintf(buf, PAGE_SIZE, "%s:\n", "OD_SCLK"); 4617 for (i = 0; i < odn_sclk_table->num_of_pl; i++) 4618 size += snprintf(buf + size, PAGE_SIZE - size, "%d: %10uMHz %10umV\n", 4619 i, odn_sclk_table->entries[i].clock/100, 4620 odn_sclk_table->entries[i].vddc); 4621 } 4622 break; 4623 case OD_MCLK: 4624 if (hwmgr->od_enabled) { 4625 size = snprintf(buf, PAGE_SIZE, "%s:\n", "OD_MCLK"); 4626 for (i = 0; i < odn_mclk_table->num_of_pl; i++) 4627 size += snprintf(buf + size, PAGE_SIZE - size, "%d: %10uMHz %10umV\n", 4628 i, odn_mclk_table->entries[i].clock/100, 4629 odn_mclk_table->entries[i].vddc); 4630 } 4631 break; 4632 case OD_RANGE: 4633 if (hwmgr->od_enabled) { 4634 size = snprintf(buf, PAGE_SIZE, "%s:\n", "OD_RANGE"); 4635 size += snprintf(buf + size, PAGE_SIZE - size, "SCLK: %7uMHz %10uMHz\n", 4636 data->golden_dpm_table.sclk_table.dpm_levels[0].value/100, 4637 hwmgr->platform_descriptor.overdriveLimit.engineClock/100); 4638 size += snprintf(buf + size, PAGE_SIZE - size, "MCLK: %7uMHz %10uMHz\n", 4639 data->golden_dpm_table.mclk_table.dpm_levels[0].value/100, 4640 hwmgr->platform_descriptor.overdriveLimit.memoryClock/100); 4641 size += snprintf(buf + size, PAGE_SIZE - size, "VDDC: %7umV %11umV\n", 4642 data->odn_dpm_table.min_vddc, 4643 data->odn_dpm_table.max_vddc); 4644 } 4645 break; 4646 default: 4647 break; 4648 } 4649 return size; 4650 } 4651 4652 static void smu7_set_fan_control_mode(struct pp_hwmgr *hwmgr, uint32_t mode) 4653 { 4654 switch (mode) { 4655 case AMD_FAN_CTRL_NONE: 4656 smu7_fan_ctrl_set_fan_speed_percent(hwmgr, 100); 4657 break; 4658 case AMD_FAN_CTRL_MANUAL: 4659 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, 4660 PHM_PlatformCaps_MicrocodeFanControl)) 4661 smu7_fan_ctrl_stop_smc_fan_control(hwmgr); 4662 break; 4663 case AMD_FAN_CTRL_AUTO: 4664 if (!smu7_fan_ctrl_set_static_mode(hwmgr, mode)) 4665 smu7_fan_ctrl_start_smc_fan_control(hwmgr); 4666 break; 4667 default: 4668 break; 4669 } 4670 } 4671 4672 static uint32_t smu7_get_fan_control_mode(struct pp_hwmgr *hwmgr) 4673 { 4674 return hwmgr->fan_ctrl_enabled ? AMD_FAN_CTRL_AUTO : AMD_FAN_CTRL_MANUAL; 4675 } 4676 4677 static int smu7_get_sclk_od(struct pp_hwmgr *hwmgr) 4678 { 4679 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 4680 struct smu7_single_dpm_table *sclk_table = &(data->dpm_table.sclk_table); 4681 struct smu7_single_dpm_table *golden_sclk_table = 4682 &(data->golden_dpm_table.sclk_table); 4683 int value = sclk_table->dpm_levels[sclk_table->count - 1].value; 4684 int golden_value = golden_sclk_table->dpm_levels 4685 [golden_sclk_table->count - 1].value; 4686 4687 value -= golden_value; 4688 value = DIV_ROUND_UP(value * 100, golden_value); 4689 4690 return value; 4691 } 4692 4693 static int smu7_set_sclk_od(struct pp_hwmgr *hwmgr, uint32_t value) 4694 { 4695 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 4696 struct smu7_single_dpm_table *golden_sclk_table = 4697 &(data->golden_dpm_table.sclk_table); 4698 struct pp_power_state *ps; 4699 struct smu7_power_state *smu7_ps; 4700 4701 if (value > 20) 4702 value = 20; 4703 4704 ps = hwmgr->request_ps; 4705 4706 if (ps == NULL) 4707 return -EINVAL; 4708 4709 smu7_ps = cast_phw_smu7_power_state(&ps->hardware); 4710 4711 smu7_ps->performance_levels[smu7_ps->performance_level_count - 1].engine_clock = 4712 golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value * 4713 value / 100 + 4714 golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value; 4715 4716 return 0; 4717 } 4718 4719 static int smu7_get_mclk_od(struct pp_hwmgr *hwmgr) 4720 { 4721 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 4722 struct smu7_single_dpm_table *mclk_table = &(data->dpm_table.mclk_table); 4723 struct smu7_single_dpm_table *golden_mclk_table = 4724 &(data->golden_dpm_table.mclk_table); 4725 int value = mclk_table->dpm_levels[mclk_table->count - 1].value; 4726 int golden_value = golden_mclk_table->dpm_levels 4727 [golden_mclk_table->count - 1].value; 4728 4729 value -= golden_value; 4730 value = DIV_ROUND_UP(value * 100, golden_value); 4731 4732 return value; 4733 } 4734 4735 static int smu7_set_mclk_od(struct pp_hwmgr *hwmgr, uint32_t value) 4736 { 4737 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 4738 struct smu7_single_dpm_table *golden_mclk_table = 4739 &(data->golden_dpm_table.mclk_table); 4740 struct pp_power_state *ps; 4741 struct smu7_power_state *smu7_ps; 4742 4743 if (value > 20) 4744 value = 20; 4745 4746 ps = hwmgr->request_ps; 4747 4748 if (ps == NULL) 4749 return -EINVAL; 4750 4751 smu7_ps = cast_phw_smu7_power_state(&ps->hardware); 4752 4753 smu7_ps->performance_levels[smu7_ps->performance_level_count - 1].memory_clock = 4754 golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value * 4755 value / 100 + 4756 golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value; 4757 4758 return 0; 4759 } 4760 4761 4762 static int smu7_get_sclks(struct pp_hwmgr *hwmgr, struct amd_pp_clocks *clocks) 4763 { 4764 struct phm_ppt_v1_information *table_info = 4765 (struct phm_ppt_v1_information *)hwmgr->pptable; 4766 struct phm_ppt_v1_clock_voltage_dependency_table *dep_sclk_table = NULL; 4767 struct phm_clock_voltage_dependency_table *sclk_table; 4768 int i; 4769 4770 if (hwmgr->pp_table_version == PP_TABLE_V1) { 4771 if (table_info == NULL || table_info->vdd_dep_on_sclk == NULL) 4772 return -EINVAL; 4773 dep_sclk_table = table_info->vdd_dep_on_sclk; 4774 for (i = 0; i < dep_sclk_table->count; i++) 4775 clocks->clock[i] = dep_sclk_table->entries[i].clk * 10; 4776 clocks->count = dep_sclk_table->count; 4777 } else if (hwmgr->pp_table_version == PP_TABLE_V0) { 4778 sclk_table = hwmgr->dyn_state.vddc_dependency_on_sclk; 4779 for (i = 0; i < sclk_table->count; i++) 4780 clocks->clock[i] = sclk_table->entries[i].clk * 10; 4781 clocks->count = sclk_table->count; 4782 } 4783 4784 return 0; 4785 } 4786 4787 static uint32_t smu7_get_mem_latency(struct pp_hwmgr *hwmgr, uint32_t clk) 4788 { 4789 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 4790 4791 if (clk >= MEM_FREQ_LOW_LATENCY && clk < MEM_FREQ_HIGH_LATENCY) 4792 return data->mem_latency_high; 4793 else if (clk >= MEM_FREQ_HIGH_LATENCY) 4794 return data->mem_latency_low; 4795 else 4796 return MEM_LATENCY_ERR; 4797 } 4798 4799 static int smu7_get_mclks(struct pp_hwmgr *hwmgr, struct amd_pp_clocks *clocks) 4800 { 4801 struct phm_ppt_v1_information *table_info = 4802 (struct phm_ppt_v1_information *)hwmgr->pptable; 4803 struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table; 4804 int i; 4805 struct phm_clock_voltage_dependency_table *mclk_table; 4806 4807 if (hwmgr->pp_table_version == PP_TABLE_V1) { 4808 if (table_info == NULL) 4809 return -EINVAL; 4810 dep_mclk_table = table_info->vdd_dep_on_mclk; 4811 for (i = 0; i < dep_mclk_table->count; i++) { 4812 clocks->clock[i] = dep_mclk_table->entries[i].clk * 10; 4813 clocks->latency[i] = smu7_get_mem_latency(hwmgr, 4814 dep_mclk_table->entries[i].clk); 4815 } 4816 clocks->count = dep_mclk_table->count; 4817 } else if (hwmgr->pp_table_version == PP_TABLE_V0) { 4818 mclk_table = hwmgr->dyn_state.vddc_dependency_on_mclk; 4819 for (i = 0; i < mclk_table->count; i++) 4820 clocks->clock[i] = mclk_table->entries[i].clk * 10; 4821 clocks->count = mclk_table->count; 4822 } 4823 return 0; 4824 } 4825 4826 static int smu7_get_clock_by_type(struct pp_hwmgr *hwmgr, enum amd_pp_clock_type type, 4827 struct amd_pp_clocks *clocks) 4828 { 4829 switch (type) { 4830 case amd_pp_sys_clock: 4831 smu7_get_sclks(hwmgr, clocks); 4832 break; 4833 case amd_pp_mem_clock: 4834 smu7_get_mclks(hwmgr, clocks); 4835 break; 4836 default: 4837 return -EINVAL; 4838 } 4839 4840 return 0; 4841 } 4842 4843 static int smu7_get_sclks_with_latency(struct pp_hwmgr *hwmgr, 4844 struct pp_clock_levels_with_latency *clocks) 4845 { 4846 struct phm_ppt_v1_information *table_info = 4847 (struct phm_ppt_v1_information *)hwmgr->pptable; 4848 struct phm_ppt_v1_clock_voltage_dependency_table *dep_sclk_table = 4849 table_info->vdd_dep_on_sclk; 4850 int i; 4851 4852 clocks->num_levels = 0; 4853 for (i = 0; i < dep_sclk_table->count; i++) { 4854 if (dep_sclk_table->entries[i].clk) { 4855 clocks->data[clocks->num_levels].clocks_in_khz = 4856 dep_sclk_table->entries[i].clk * 10; 4857 clocks->num_levels++; 4858 } 4859 } 4860 4861 return 0; 4862 } 4863 4864 static int smu7_get_mclks_with_latency(struct pp_hwmgr *hwmgr, 4865 struct pp_clock_levels_with_latency *clocks) 4866 { 4867 struct phm_ppt_v1_information *table_info = 4868 (struct phm_ppt_v1_information *)hwmgr->pptable; 4869 struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table = 4870 table_info->vdd_dep_on_mclk; 4871 int i; 4872 4873 clocks->num_levels = 0; 4874 for (i = 0; i < dep_mclk_table->count; i++) { 4875 if (dep_mclk_table->entries[i].clk) { 4876 clocks->data[clocks->num_levels].clocks_in_khz = 4877 dep_mclk_table->entries[i].clk * 10; 4878 clocks->data[clocks->num_levels].latency_in_us = 4879 smu7_get_mem_latency(hwmgr, dep_mclk_table->entries[i].clk); 4880 clocks->num_levels++; 4881 } 4882 } 4883 4884 return 0; 4885 } 4886 4887 static int smu7_get_clock_by_type_with_latency(struct pp_hwmgr *hwmgr, 4888 enum amd_pp_clock_type type, 4889 struct pp_clock_levels_with_latency *clocks) 4890 { 4891 if (!(hwmgr->chip_id >= CHIP_POLARIS10 && 4892 hwmgr->chip_id <= CHIP_VEGAM)) 4893 return -EINVAL; 4894 4895 switch (type) { 4896 case amd_pp_sys_clock: 4897 smu7_get_sclks_with_latency(hwmgr, clocks); 4898 break; 4899 case amd_pp_mem_clock: 4900 smu7_get_mclks_with_latency(hwmgr, clocks); 4901 break; 4902 default: 4903 return -EINVAL; 4904 } 4905 4906 return 0; 4907 } 4908 4909 static int smu7_notify_cac_buffer_info(struct pp_hwmgr *hwmgr, 4910 uint32_t virtual_addr_low, 4911 uint32_t virtual_addr_hi, 4912 uint32_t mc_addr_low, 4913 uint32_t mc_addr_hi, 4914 uint32_t size) 4915 { 4916 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 4917 4918 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 4919 data->soft_regs_start + 4920 smum_get_offsetof(hwmgr, 4921 SMU_SoftRegisters, DRAM_LOG_ADDR_H), 4922 mc_addr_hi); 4923 4924 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 4925 data->soft_regs_start + 4926 smum_get_offsetof(hwmgr, 4927 SMU_SoftRegisters, DRAM_LOG_ADDR_L), 4928 mc_addr_low); 4929 4930 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 4931 data->soft_regs_start + 4932 smum_get_offsetof(hwmgr, 4933 SMU_SoftRegisters, DRAM_LOG_PHY_ADDR_H), 4934 virtual_addr_hi); 4935 4936 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 4937 data->soft_regs_start + 4938 smum_get_offsetof(hwmgr, 4939 SMU_SoftRegisters, DRAM_LOG_PHY_ADDR_L), 4940 virtual_addr_low); 4941 4942 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 4943 data->soft_regs_start + 4944 smum_get_offsetof(hwmgr, 4945 SMU_SoftRegisters, DRAM_LOG_BUFF_SIZE), 4946 size); 4947 return 0; 4948 } 4949 4950 static int smu7_get_max_high_clocks(struct pp_hwmgr *hwmgr, 4951 struct amd_pp_simple_clock_info *clocks) 4952 { 4953 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 4954 struct smu7_single_dpm_table *sclk_table = &(data->dpm_table.sclk_table); 4955 struct smu7_single_dpm_table *mclk_table = &(data->dpm_table.mclk_table); 4956 4957 if (clocks == NULL) 4958 return -EINVAL; 4959 4960 clocks->memory_max_clock = mclk_table->count > 1 ? 4961 mclk_table->dpm_levels[mclk_table->count-1].value : 4962 mclk_table->dpm_levels[0].value; 4963 clocks->engine_max_clock = sclk_table->count > 1 ? 4964 sclk_table->dpm_levels[sclk_table->count-1].value : 4965 sclk_table->dpm_levels[0].value; 4966 return 0; 4967 } 4968 4969 static int smu7_get_thermal_temperature_range(struct pp_hwmgr *hwmgr, 4970 struct PP_TemperatureRange *thermal_data) 4971 { 4972 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 4973 struct phm_ppt_v1_information *table_info = 4974 (struct phm_ppt_v1_information *)hwmgr->pptable; 4975 4976 memcpy(thermal_data, &SMU7ThermalPolicy[0], sizeof(struct PP_TemperatureRange)); 4977 4978 if (hwmgr->pp_table_version == PP_TABLE_V1) 4979 thermal_data->max = table_info->cac_dtp_table->usSoftwareShutdownTemp * 4980 PP_TEMPERATURE_UNITS_PER_CENTIGRADES; 4981 else if (hwmgr->pp_table_version == PP_TABLE_V0) 4982 thermal_data->max = data->thermal_temp_setting.temperature_shutdown * 4983 PP_TEMPERATURE_UNITS_PER_CENTIGRADES; 4984 4985 return 0; 4986 } 4987 4988 static bool smu7_check_clk_voltage_valid(struct pp_hwmgr *hwmgr, 4989 enum PP_OD_DPM_TABLE_COMMAND type, 4990 uint32_t clk, 4991 uint32_t voltage) 4992 { 4993 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 4994 4995 if (voltage < data->odn_dpm_table.min_vddc || voltage > data->odn_dpm_table.max_vddc) { 4996 pr_info("OD voltage is out of range [%d - %d] mV\n", 4997 data->odn_dpm_table.min_vddc, 4998 data->odn_dpm_table.max_vddc); 4999 return false; 5000 } 5001 5002 if (type == PP_OD_EDIT_SCLK_VDDC_TABLE) { 5003 if (data->golden_dpm_table.sclk_table.dpm_levels[0].value > clk || 5004 hwmgr->platform_descriptor.overdriveLimit.engineClock < clk) { 5005 pr_info("OD engine clock is out of range [%d - %d] MHz\n", 5006 data->golden_dpm_table.sclk_table.dpm_levels[0].value/100, 5007 hwmgr->platform_descriptor.overdriveLimit.engineClock/100); 5008 return false; 5009 } 5010 } else if (type == PP_OD_EDIT_MCLK_VDDC_TABLE) { 5011 if (data->golden_dpm_table.mclk_table.dpm_levels[0].value > clk || 5012 hwmgr->platform_descriptor.overdriveLimit.memoryClock < clk) { 5013 pr_info("OD memory clock is out of range [%d - %d] MHz\n", 5014 data->golden_dpm_table.mclk_table.dpm_levels[0].value/100, 5015 hwmgr->platform_descriptor.overdriveLimit.memoryClock/100); 5016 return false; 5017 } 5018 } else { 5019 return false; 5020 } 5021 5022 return true; 5023 } 5024 5025 static int smu7_odn_edit_dpm_table(struct pp_hwmgr *hwmgr, 5026 enum PP_OD_DPM_TABLE_COMMAND type, 5027 long *input, uint32_t size) 5028 { 5029 uint32_t i; 5030 struct phm_odn_clock_levels *podn_dpm_table_in_backend = NULL; 5031 struct smu7_odn_clock_voltage_dependency_table *podn_vdd_dep_in_backend = NULL; 5032 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 5033 5034 uint32_t input_clk; 5035 uint32_t input_vol; 5036 uint32_t input_level; 5037 5038 PP_ASSERT_WITH_CODE(input, "NULL user input for clock and voltage", 5039 return -EINVAL); 5040 5041 if (!hwmgr->od_enabled) { 5042 pr_info("OverDrive feature not enabled\n"); 5043 return -EINVAL; 5044 } 5045 5046 if (PP_OD_EDIT_SCLK_VDDC_TABLE == type) { 5047 podn_dpm_table_in_backend = &data->odn_dpm_table.odn_core_clock_dpm_levels; 5048 podn_vdd_dep_in_backend = &data->odn_dpm_table.vdd_dependency_on_sclk; 5049 PP_ASSERT_WITH_CODE((podn_dpm_table_in_backend && podn_vdd_dep_in_backend), 5050 "Failed to get ODN SCLK and Voltage tables", 5051 return -EINVAL); 5052 } else if (PP_OD_EDIT_MCLK_VDDC_TABLE == type) { 5053 podn_dpm_table_in_backend = &data->odn_dpm_table.odn_memory_clock_dpm_levels; 5054 podn_vdd_dep_in_backend = &data->odn_dpm_table.vdd_dependency_on_mclk; 5055 5056 PP_ASSERT_WITH_CODE((podn_dpm_table_in_backend && podn_vdd_dep_in_backend), 5057 "Failed to get ODN MCLK and Voltage tables", 5058 return -EINVAL); 5059 } else if (PP_OD_RESTORE_DEFAULT_TABLE == type) { 5060 smu7_odn_initial_default_setting(hwmgr); 5061 return 0; 5062 } else if (PP_OD_COMMIT_DPM_TABLE == type) { 5063 smu7_check_dpm_table_updated(hwmgr); 5064 return 0; 5065 } else { 5066 return -EINVAL; 5067 } 5068 5069 for (i = 0; i < size; i += 3) { 5070 if (i + 3 > size || input[i] >= podn_dpm_table_in_backend->num_of_pl) { 5071 pr_info("invalid clock voltage input \n"); 5072 return 0; 5073 } 5074 input_level = input[i]; 5075 input_clk = input[i+1] * 100; 5076 input_vol = input[i+2]; 5077 5078 if (smu7_check_clk_voltage_valid(hwmgr, type, input_clk, input_vol)) { 5079 podn_dpm_table_in_backend->entries[input_level].clock = input_clk; 5080 podn_vdd_dep_in_backend->entries[input_level].clk = input_clk; 5081 podn_dpm_table_in_backend->entries[input_level].vddc = input_vol; 5082 podn_vdd_dep_in_backend->entries[input_level].vddc = input_vol; 5083 podn_vdd_dep_in_backend->entries[input_level].vddgfx = input_vol; 5084 } else { 5085 return -EINVAL; 5086 } 5087 } 5088 5089 return 0; 5090 } 5091 5092 static int smu7_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf) 5093 { 5094 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 5095 uint32_t i, size = 0; 5096 uint32_t len; 5097 5098 static const char *profile_name[7] = {"BOOTUP_DEFAULT", 5099 "3D_FULL_SCREEN", 5100 "POWER_SAVING", 5101 "VIDEO", 5102 "VR", 5103 "COMPUTE", 5104 "CUSTOM"}; 5105 5106 static const char *title[8] = {"NUM", 5107 "MODE_NAME", 5108 "SCLK_UP_HYST", 5109 "SCLK_DOWN_HYST", 5110 "SCLK_ACTIVE_LEVEL", 5111 "MCLK_UP_HYST", 5112 "MCLK_DOWN_HYST", 5113 "MCLK_ACTIVE_LEVEL"}; 5114 5115 if (!buf) 5116 return -EINVAL; 5117 5118 size += snprintf(buf + size, PAGE_SIZE - size, "%s %16s %16s %16s %16s %16s %16s %16s\n", 5119 title[0], title[1], title[2], title[3], 5120 title[4], title[5], title[6], title[7]); 5121 5122 len = ARRAY_SIZE(smu7_profiling); 5123 5124 for (i = 0; i < len; i++) { 5125 if (i == hwmgr->power_profile_mode) { 5126 size += snprintf(buf + size, PAGE_SIZE - size, "%3d %14s %s: %8d %16d %16d %16d %16d %16d\n", 5127 i, profile_name[i], "*", 5128 data->current_profile_setting.sclk_up_hyst, 5129 data->current_profile_setting.sclk_down_hyst, 5130 data->current_profile_setting.sclk_activity, 5131 data->current_profile_setting.mclk_up_hyst, 5132 data->current_profile_setting.mclk_down_hyst, 5133 data->current_profile_setting.mclk_activity); 5134 continue; 5135 } 5136 if (smu7_profiling[i].bupdate_sclk) 5137 size += snprintf(buf + size, PAGE_SIZE - size, "%3d %16s: %8d %16d %16d ", 5138 i, profile_name[i], smu7_profiling[i].sclk_up_hyst, 5139 smu7_profiling[i].sclk_down_hyst, 5140 smu7_profiling[i].sclk_activity); 5141 else 5142 size += snprintf(buf + size, PAGE_SIZE - size, "%3d %16s: %8s %16s %16s ", 5143 i, profile_name[i], "-", "-", "-"); 5144 5145 if (smu7_profiling[i].bupdate_mclk) 5146 size += snprintf(buf + size, PAGE_SIZE - size, "%16d %16d %16d\n", 5147 smu7_profiling[i].mclk_up_hyst, 5148 smu7_profiling[i].mclk_down_hyst, 5149 smu7_profiling[i].mclk_activity); 5150 else 5151 size += snprintf(buf + size, PAGE_SIZE - size, "%16s %16s %16s\n", 5152 "-", "-", "-"); 5153 } 5154 5155 return size; 5156 } 5157 5158 static void smu7_patch_compute_profile_mode(struct pp_hwmgr *hwmgr, 5159 enum PP_SMC_POWER_PROFILE requst) 5160 { 5161 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 5162 uint32_t tmp, level; 5163 5164 if (requst == PP_SMC_POWER_PROFILE_COMPUTE) { 5165 if (data->dpm_level_enable_mask.sclk_dpm_enable_mask) { 5166 level = 0; 5167 tmp = data->dpm_level_enable_mask.sclk_dpm_enable_mask; 5168 while (tmp >>= 1) 5169 level++; 5170 if (level > 0) 5171 smu7_force_clock_level(hwmgr, PP_SCLK, 3 << (level-1)); 5172 } 5173 } else if (hwmgr->power_profile_mode == PP_SMC_POWER_PROFILE_COMPUTE) { 5174 smu7_force_clock_level(hwmgr, PP_SCLK, data->dpm_level_enable_mask.sclk_dpm_enable_mask); 5175 } 5176 } 5177 5178 static int smu7_set_power_profile_mode(struct pp_hwmgr *hwmgr, long *input, uint32_t size) 5179 { 5180 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 5181 struct profile_mode_setting tmp; 5182 enum PP_SMC_POWER_PROFILE mode; 5183 5184 if (input == NULL) 5185 return -EINVAL; 5186 5187 mode = input[size]; 5188 switch (mode) { 5189 case PP_SMC_POWER_PROFILE_CUSTOM: 5190 if (size < 8 && size != 0) 5191 return -EINVAL; 5192 /* If only CUSTOM is passed in, use the saved values. Check 5193 * that we actually have a CUSTOM profile by ensuring that 5194 * the "use sclk" or the "use mclk" bits are set 5195 */ 5196 tmp = smu7_profiling[PP_SMC_POWER_PROFILE_CUSTOM]; 5197 if (size == 0) { 5198 if (tmp.bupdate_sclk == 0 && tmp.bupdate_mclk == 0) 5199 return -EINVAL; 5200 } else { 5201 tmp.bupdate_sclk = input[0]; 5202 tmp.sclk_up_hyst = input[1]; 5203 tmp.sclk_down_hyst = input[2]; 5204 tmp.sclk_activity = input[3]; 5205 tmp.bupdate_mclk = input[4]; 5206 tmp.mclk_up_hyst = input[5]; 5207 tmp.mclk_down_hyst = input[6]; 5208 tmp.mclk_activity = input[7]; 5209 smu7_profiling[PP_SMC_POWER_PROFILE_CUSTOM] = tmp; 5210 } 5211 if (!smum_update_dpm_settings(hwmgr, &tmp)) { 5212 memcpy(&data->current_profile_setting, &tmp, sizeof(struct profile_mode_setting)); 5213 hwmgr->power_profile_mode = mode; 5214 } 5215 break; 5216 case PP_SMC_POWER_PROFILE_FULLSCREEN3D: 5217 case PP_SMC_POWER_PROFILE_POWERSAVING: 5218 case PP_SMC_POWER_PROFILE_VIDEO: 5219 case PP_SMC_POWER_PROFILE_VR: 5220 case PP_SMC_POWER_PROFILE_COMPUTE: 5221 if (mode == hwmgr->power_profile_mode) 5222 return 0; 5223 5224 memcpy(&tmp, &smu7_profiling[mode], sizeof(struct profile_mode_setting)); 5225 if (!smum_update_dpm_settings(hwmgr, &tmp)) { 5226 if (tmp.bupdate_sclk) { 5227 data->current_profile_setting.bupdate_sclk = tmp.bupdate_sclk; 5228 data->current_profile_setting.sclk_up_hyst = tmp.sclk_up_hyst; 5229 data->current_profile_setting.sclk_down_hyst = tmp.sclk_down_hyst; 5230 data->current_profile_setting.sclk_activity = tmp.sclk_activity; 5231 } 5232 if (tmp.bupdate_mclk) { 5233 data->current_profile_setting.bupdate_mclk = tmp.bupdate_mclk; 5234 data->current_profile_setting.mclk_up_hyst = tmp.mclk_up_hyst; 5235 data->current_profile_setting.mclk_down_hyst = tmp.mclk_down_hyst; 5236 data->current_profile_setting.mclk_activity = tmp.mclk_activity; 5237 } 5238 smu7_patch_compute_profile_mode(hwmgr, mode); 5239 hwmgr->power_profile_mode = mode; 5240 } 5241 break; 5242 default: 5243 return -EINVAL; 5244 } 5245 5246 return 0; 5247 } 5248 5249 static int smu7_get_performance_level(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state, 5250 PHM_PerformanceLevelDesignation designation, uint32_t index, 5251 PHM_PerformanceLevel *level) 5252 { 5253 const struct smu7_power_state *ps; 5254 uint32_t i; 5255 5256 if (level == NULL || hwmgr == NULL || state == NULL) 5257 return -EINVAL; 5258 5259 ps = cast_const_phw_smu7_power_state(state); 5260 5261 i = index > ps->performance_level_count - 1 ? 5262 ps->performance_level_count - 1 : index; 5263 5264 level->coreClock = ps->performance_levels[i].engine_clock; 5265 level->memory_clock = ps->performance_levels[i].memory_clock; 5266 5267 return 0; 5268 } 5269 5270 static int smu7_power_off_asic(struct pp_hwmgr *hwmgr) 5271 { 5272 int result; 5273 5274 result = smu7_disable_dpm_tasks(hwmgr); 5275 PP_ASSERT_WITH_CODE((0 == result), 5276 "[disable_dpm_tasks] Failed to disable DPM!", 5277 ); 5278 5279 return result; 5280 } 5281 5282 static const struct pp_hwmgr_func smu7_hwmgr_funcs = { 5283 .backend_init = &smu7_hwmgr_backend_init, 5284 .backend_fini = &smu7_hwmgr_backend_fini, 5285 .asic_setup = &smu7_setup_asic_task, 5286 .dynamic_state_management_enable = &smu7_enable_dpm_tasks, 5287 .apply_state_adjust_rules = smu7_apply_state_adjust_rules, 5288 .force_dpm_level = &smu7_force_dpm_level, 5289 .power_state_set = smu7_set_power_state_tasks, 5290 .get_power_state_size = smu7_get_power_state_size, 5291 .get_mclk = smu7_dpm_get_mclk, 5292 .get_sclk = smu7_dpm_get_sclk, 5293 .patch_boot_state = smu7_dpm_patch_boot_state, 5294 .get_pp_table_entry = smu7_get_pp_table_entry, 5295 .get_num_of_pp_table_entries = smu7_get_number_of_powerplay_table_entries, 5296 .powerdown_uvd = smu7_powerdown_uvd, 5297 .powergate_uvd = smu7_powergate_uvd, 5298 .powergate_vce = smu7_powergate_vce, 5299 .disable_clock_power_gating = smu7_disable_clock_power_gating, 5300 .update_clock_gatings = smu7_update_clock_gatings, 5301 .notify_smc_display_config_after_ps_adjustment = smu7_notify_smc_display_config_after_ps_adjustment, 5302 .display_config_changed = smu7_display_configuration_changed_task, 5303 .set_max_fan_pwm_output = smu7_set_max_fan_pwm_output, 5304 .set_max_fan_rpm_output = smu7_set_max_fan_rpm_output, 5305 .stop_thermal_controller = smu7_thermal_stop_thermal_controller, 5306 .get_fan_speed_info = smu7_fan_ctrl_get_fan_speed_info, 5307 .get_fan_speed_percent = smu7_fan_ctrl_get_fan_speed_percent, 5308 .set_fan_speed_percent = smu7_fan_ctrl_set_fan_speed_percent, 5309 .reset_fan_speed_to_default = smu7_fan_ctrl_reset_fan_speed_to_default, 5310 .get_fan_speed_rpm = smu7_fan_ctrl_get_fan_speed_rpm, 5311 .set_fan_speed_rpm = smu7_fan_ctrl_set_fan_speed_rpm, 5312 .uninitialize_thermal_controller = smu7_thermal_ctrl_uninitialize_thermal_controller, 5313 .register_irq_handlers = smu7_register_irq_handlers, 5314 .check_smc_update_required_for_display_configuration = smu7_check_smc_update_required_for_display_configuration, 5315 .check_states_equal = smu7_check_states_equal, 5316 .set_fan_control_mode = smu7_set_fan_control_mode, 5317 .get_fan_control_mode = smu7_get_fan_control_mode, 5318 .force_clock_level = smu7_force_clock_level, 5319 .print_clock_levels = smu7_print_clock_levels, 5320 .powergate_gfx = smu7_powergate_gfx, 5321 .get_sclk_od = smu7_get_sclk_od, 5322 .set_sclk_od = smu7_set_sclk_od, 5323 .get_mclk_od = smu7_get_mclk_od, 5324 .set_mclk_od = smu7_set_mclk_od, 5325 .get_clock_by_type = smu7_get_clock_by_type, 5326 .get_clock_by_type_with_latency = smu7_get_clock_by_type_with_latency, 5327 .read_sensor = smu7_read_sensor, 5328 .dynamic_state_management_disable = smu7_disable_dpm_tasks, 5329 .avfs_control = smu7_avfs_control, 5330 .disable_smc_firmware_ctf = smu7_thermal_disable_alert, 5331 .start_thermal_controller = smu7_start_thermal_controller, 5332 .notify_cac_buffer_info = smu7_notify_cac_buffer_info, 5333 .get_max_high_clocks = smu7_get_max_high_clocks, 5334 .get_thermal_temperature_range = smu7_get_thermal_temperature_range, 5335 .odn_edit_dpm_table = smu7_odn_edit_dpm_table, 5336 .set_power_limit = smu7_set_power_limit, 5337 .get_power_profile_mode = smu7_get_power_profile_mode, 5338 .set_power_profile_mode = smu7_set_power_profile_mode, 5339 .get_performance_level = smu7_get_performance_level, 5340 .get_asic_baco_capability = smu7_baco_get_capability, 5341 .get_asic_baco_state = smu7_baco_get_state, 5342 .set_asic_baco_state = smu7_baco_set_state, 5343 .power_off_asic = smu7_power_off_asic, 5344 }; 5345 5346 uint8_t smu7_get_sleep_divider_id_from_clock(uint32_t clock, 5347 uint32_t clock_insr) 5348 { 5349 uint8_t i; 5350 uint32_t temp; 5351 uint32_t min = max(clock_insr, (uint32_t)SMU7_MINIMUM_ENGINE_CLOCK); 5352 5353 PP_ASSERT_WITH_CODE((clock >= min), "Engine clock can't satisfy stutter requirement!", return 0); 5354 for (i = SMU7_MAX_DEEPSLEEP_DIVIDER_ID; ; i--) { 5355 temp = clock >> i; 5356 5357 if (temp >= min || i == 0) 5358 break; 5359 } 5360 return i; 5361 } 5362 5363 int smu7_init_function_pointers(struct pp_hwmgr *hwmgr) 5364 { 5365 hwmgr->hwmgr_func = &smu7_hwmgr_funcs; 5366 if (hwmgr->pp_table_version == PP_TABLE_V0) 5367 hwmgr->pptable_func = &pptable_funcs; 5368 else if (hwmgr->pp_table_version == PP_TABLE_V1) 5369 hwmgr->pptable_func = &pptable_v1_0_funcs; 5370 5371 return 0; 5372 } 5373