1 /* $NetBSD: amdgpu_fiji_smumgr.c,v 1.3 2021/12/19 12:02:40 riastradh Exp $ */ 2 3 /* 4 * Copyright 2015 Advanced Micro Devices, Inc. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 * OTHER DEALINGS IN THE SOFTWARE. 23 * 24 */ 25 26 #include <sys/cdefs.h> 27 __KERNEL_RCSID(0, "$NetBSD: amdgpu_fiji_smumgr.c,v 1.3 2021/12/19 12:02:40 riastradh Exp $"); 28 29 #include "pp_debug.h" 30 #include "smumgr.h" 31 #include "smu7_dyn_defaults.h" 32 #include "smu73.h" 33 #include "smu_ucode_xfer_vi.h" 34 #include "fiji_smumgr.h" 35 #include "fiji_ppsmc.h" 36 #include "smu73_discrete.h" 37 #include "ppatomctrl.h" 38 #include "smu/smu_7_1_3_d.h" 39 #include "smu/smu_7_1_3_sh_mask.h" 40 #include "gmc/gmc_8_1_d.h" 41 #include "gmc/gmc_8_1_sh_mask.h" 42 #include "oss/oss_3_0_d.h" 43 #include "gca/gfx_8_0_d.h" 44 #include "bif/bif_5_0_d.h" 45 #include "bif/bif_5_0_sh_mask.h" 46 #include "dce/dce_10_0_d.h" 47 #include "dce/dce_10_0_sh_mask.h" 48 #include "hardwaremanager.h" 49 #include "cgs_common.h" 50 #include "atombios.h" 51 #include "pppcielanes.h" 52 #include "hwmgr.h" 53 #include "smu7_hwmgr.h" 54 55 56 #define AVFS_EN_MSB 1568 57 #define AVFS_EN_LSB 1568 58 59 #define FIJI_SMC_SIZE 0x20000 60 61 #define POWERTUNE_DEFAULT_SET_MAX 1 62 #define VDDC_VDDCI_DELTA 300 63 #define MC_CG_ARB_FREQ_F1 0x0b 64 65 /* [2.5%,~2.5%] Clock stretched is multiple of 2.5% vs 66 * not and [Fmin, Fmax, LDO_REFSEL, USE_FOR_LOW_FREQ] 67 */ 68 static const uint16_t fiji_clock_stretcher_lookup_table[2][4] = { 69 {600, 1050, 3, 0}, {600, 1050, 6, 1} }; 70 71 /* [FF, SS] type, [] 4 voltage ranges, and 72 * [Floor Freq, Boundary Freq, VID min , VID max] 73 */ 74 static const uint32_t fiji_clock_stretcher_ddt_table[2][4][4] = { 75 { {265, 529, 120, 128}, {325, 650, 96, 119}, {430, 860, 32, 95}, {0, 0, 0, 31} }, 76 { {275, 550, 104, 112}, {319, 638, 96, 103}, {360, 720, 64, 95}, {384, 768, 32, 63} } }; 77 78 /* [Use_For_Low_freq] value, [0%, 5%, 10%, 7.14%, 14.28%, 20%] 79 * (coming from PWR_CKS_CNTL.stretch_amount reg spec) 80 */ 81 static const uint8_t fiji_clock_stretch_amount_conversion[2][6] = { 82 {0, 1, 3, 2, 4, 5}, {0, 2, 4, 5, 6, 5} }; 83 84 static const struct fiji_pt_defaults fiji_power_tune_data_set_array[POWERTUNE_DEFAULT_SET_MAX] = { 85 /*sviLoadLIneEn, SviLoadLineVddC, TDC_VDDC_ThrottleReleaseLimitPerc */ 86 {1, 0xF, 0xFD, 87 /* TDC_MAWt, TdcWaterfallCtl, DTEAmbientTempBase */ 88 0x19, 5, 45} 89 }; 90 91 static const struct SMU73_Discrete_GraphicsLevel avfs_graphics_level[8] = { 92 /* Min Sclk pcie DeepSleep Activity CgSpll CgSpll spllSpread SpllSpread CcPwr CcPwr Sclk Display Enabled Enabled Voltage Power */ 93 /* Voltage, Frequency, DpmLevel, DivId, Level, FuncCntl3, FuncCntl4, Spectrum, Spectrum2, DynRm, DynRm1 Did, Watermark, ForActivity, ForThrottle, UpHyst, DownHyst, DownHyst, Throttle */ 94 { 0x3c0fd047, 0x30750000, 0x00, 0x03, 0x1e00, 0x00200410, 0x87020000, 0x21680000, 0x0c000000, 0, 0, 0x16, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 }, 95 { 0xa00fd047, 0x409c0000, 0x01, 0x04, 0x1e00, 0x00800510, 0x87020000, 0x21680000, 0x11000000, 0, 0, 0x16, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 }, 96 { 0x0410d047, 0x50c30000, 0x01, 0x00, 0x1e00, 0x00600410, 0x87020000, 0x21680000, 0x0d000000, 0, 0, 0x0e, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 }, 97 { 0x6810d047, 0x60ea0000, 0x01, 0x00, 0x1e00, 0x00800410, 0x87020000, 0x21680000, 0x0e000000, 0, 0, 0x0c, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 }, 98 { 0xcc10d047, 0xe8fd0000, 0x01, 0x00, 0x1e00, 0x00e00410, 0x87020000, 0x21680000, 0x0f000000, 0, 0, 0x0c, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 }, 99 { 0x3011d047, 0x70110100, 0x01, 0x00, 0x1e00, 0x00400510, 0x87020000, 0x21680000, 0x10000000, 0, 0, 0x0c, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 }, 100 { 0x9411d047, 0xf8240100, 0x01, 0x00, 0x1e00, 0x00a00510, 0x87020000, 0x21680000, 0x11000000, 0, 0, 0x0c, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 }, 101 { 0xf811d047, 0x80380100, 0x01, 0x00, 0x1e00, 0x00000610, 0x87020000, 0x21680000, 0x12000000, 0, 0, 0x0c, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 } 102 }; 103 104 static int fiji_start_smu_in_protection_mode(struct pp_hwmgr *hwmgr) 105 { 106 int result = 0; 107 108 /* Wait for smc boot up */ 109 /* PHM_WAIT_INDIRECT_FIELD_UNEQUAL(hwmgr, SMC_IND, 110 RCU_UC_EVENTS, boot_seq_done, 0); */ 111 112 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, 113 SMC_SYSCON_RESET_CNTL, rst_reg, 1); 114 115 result = smu7_upload_smu_firmware_image(hwmgr); 116 if (result) 117 return result; 118 119 /* Clear status */ 120 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 121 ixSMU_STATUS, 0); 122 123 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, 124 SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 0); 125 126 /* De-assert reset */ 127 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, 128 SMC_SYSCON_RESET_CNTL, rst_reg, 0); 129 130 /* Wait for ROM firmware to initialize interrupt hendler */ 131 /*SMUM_WAIT_VFPF_INDIRECT_REGISTER(hwmgr, SMC_IND, 132 SMC_INTR_CNTL_MASK_0, 0x10040, 0xFFFFFFFF); */ 133 134 /* Set SMU Auto Start */ 135 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, 136 SMU_INPUT_DATA, AUTO_START, 1); 137 138 /* Clear firmware interrupt enable flag */ 139 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 140 ixFIRMWARE_FLAGS, 0); 141 142 PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr, SMC_IND, RCU_UC_EVENTS, 143 INTERRUPTS_ENABLED, 1); 144 145 cgs_write_register(hwmgr->device, mmSMC_MSG_ARG_0, 0x20000); 146 cgs_write_register(hwmgr->device, mmSMC_MESSAGE_0, PPSMC_MSG_Test); 147 PHM_WAIT_FIELD_UNEQUAL(hwmgr, SMC_RESP_0, SMC_RESP, 0); 148 149 /* Wait for done bit to be set */ 150 PHM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(hwmgr, SMC_IND, 151 SMU_STATUS, SMU_DONE, 0); 152 153 /* Check pass/failed indicator */ 154 if (PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, 155 SMU_STATUS, SMU_PASS) != 1) { 156 PP_ASSERT_WITH_CODE(false, 157 "SMU Firmware start failed!", return -1); 158 } 159 160 /* Wait for firmware to initialize */ 161 PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr, SMC_IND, 162 FIRMWARE_FLAGS, INTERRUPTS_ENABLED, 1); 163 164 return result; 165 } 166 167 static int fiji_start_smu_in_non_protection_mode(struct pp_hwmgr *hwmgr) 168 { 169 int result = 0; 170 171 /* wait for smc boot up */ 172 PHM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(hwmgr, SMC_IND, 173 RCU_UC_EVENTS, boot_seq_done, 0); 174 175 /* Clear firmware interrupt enable flag */ 176 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 177 ixFIRMWARE_FLAGS, 0); 178 179 /* Assert reset */ 180 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, 181 SMC_SYSCON_RESET_CNTL, rst_reg, 1); 182 183 result = smu7_upload_smu_firmware_image(hwmgr); 184 if (result) 185 return result; 186 187 /* Set smc instruct start point at 0x0 */ 188 smu7_program_jump_on_start(hwmgr); 189 190 /* Enable clock */ 191 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, 192 SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 0); 193 194 /* De-assert reset */ 195 PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, 196 SMC_SYSCON_RESET_CNTL, rst_reg, 0); 197 198 /* Wait for firmware to initialize */ 199 PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr, SMC_IND, 200 FIRMWARE_FLAGS, INTERRUPTS_ENABLED, 1); 201 202 return result; 203 } 204 205 static int fiji_start_avfs_btc(struct pp_hwmgr *hwmgr) 206 { 207 int result = 0; 208 struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend); 209 210 if (0 != smu_data->avfs_btc_param) { 211 if (0 != smu7_send_msg_to_smc_with_parameter(hwmgr, 212 PPSMC_MSG_PerformBtc, smu_data->avfs_btc_param)) { 213 pr_info("[AVFS][Fiji_PerformBtc] PerformBTC SMU msg failed"); 214 result = -EINVAL; 215 } 216 } 217 /* Soft-Reset to reset the engine before loading uCode */ 218 /* halt */ 219 cgs_write_register(hwmgr->device, mmCP_MEC_CNTL, 0x50000000); 220 /* reset everything */ 221 cgs_write_register(hwmgr->device, mmGRBM_SOFT_RESET, 0xffffffff); 222 /* clear reset */ 223 cgs_write_register(hwmgr->device, mmGRBM_SOFT_RESET, 0); 224 225 return result; 226 } 227 228 static int fiji_setup_graphics_level_structure(struct pp_hwmgr *hwmgr) 229 { 230 int32_t vr_config; 231 uint32_t table_start; 232 uint32_t level_addr, vr_config_addr; 233 uint32_t level_size = sizeof(avfs_graphics_level); 234 235 PP_ASSERT_WITH_CODE(0 == smu7_read_smc_sram_dword(hwmgr, 236 SMU7_FIRMWARE_HEADER_LOCATION + 237 offsetof(SMU73_Firmware_Header, DpmTable), 238 &table_start, 0x40000), 239 "[AVFS][Fiji_SetupGfxLvlStruct] SMU could not " 240 "communicate starting address of DPM table", 241 return -1;); 242 243 /* Default value for vr_config = 244 * VR_MERGED_WITH_VDDC + VR_STATIC_VOLTAGE(VDDCI) */ 245 vr_config = 0x01000500; /* Real value:0x50001 */ 246 247 vr_config_addr = table_start + 248 offsetof(SMU73_Discrete_DpmTable, VRConfig); 249 250 PP_ASSERT_WITH_CODE(0 == smu7_copy_bytes_to_smc(hwmgr, vr_config_addr, 251 (uint8_t *)&vr_config, sizeof(int32_t), 0x40000), 252 "[AVFS][Fiji_SetupGfxLvlStruct] Problems copying " 253 "vr_config value over to SMC", 254 return -1;); 255 256 level_addr = table_start + offsetof(SMU73_Discrete_DpmTable, GraphicsLevel); 257 258 PP_ASSERT_WITH_CODE(0 == smu7_copy_bytes_to_smc(hwmgr, level_addr, 259 (uint8_t *)(&avfs_graphics_level), level_size, 0x40000), 260 "[AVFS][Fiji_SetupGfxLvlStruct] Copying of DPM table failed!", 261 return -1;); 262 263 return 0; 264 } 265 266 static int fiji_avfs_event_mgr(struct pp_hwmgr *hwmgr) 267 { 268 if (!hwmgr->avfs_supported) 269 return 0; 270 271 PP_ASSERT_WITH_CODE(0 == fiji_setup_graphics_level_structure(hwmgr), 272 "[AVFS][fiji_avfs_event_mgr] Could not Copy Graphics Level" 273 " table over to SMU", 274 return -EINVAL); 275 PP_ASSERT_WITH_CODE(0 == smu7_setup_pwr_virus(hwmgr), 276 "[AVFS][fiji_avfs_event_mgr] Could not setup " 277 "Pwr Virus for AVFS ", 278 return -EINVAL); 279 PP_ASSERT_WITH_CODE(0 == fiji_start_avfs_btc(hwmgr), 280 "[AVFS][fiji_avfs_event_mgr] Failure at " 281 "fiji_start_avfs_btc. AVFS Disabled", 282 return -EINVAL); 283 284 return 0; 285 } 286 287 static int fiji_start_smu(struct pp_hwmgr *hwmgr) 288 { 289 int result = 0; 290 struct fiji_smumgr *priv = (struct fiji_smumgr *)(hwmgr->smu_backend); 291 292 /* Only start SMC if SMC RAM is not running */ 293 if (!smu7_is_smc_ram_running(hwmgr) && hwmgr->not_vf) { 294 /* Check if SMU is running in protected mode */ 295 if (0 == PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, 296 CGS_IND_REG__SMC, 297 SMU_FIRMWARE, SMU_MODE)) { 298 result = fiji_start_smu_in_non_protection_mode(hwmgr); 299 if (result) 300 return result; 301 } else { 302 result = fiji_start_smu_in_protection_mode(hwmgr); 303 if (result) 304 return result; 305 } 306 if (fiji_avfs_event_mgr(hwmgr)) 307 hwmgr->avfs_supported = false; 308 } 309 310 /* Setup SoftRegsStart here for register lookup in case 311 * DummyBackEnd is used and ProcessFirmwareHeader is not executed 312 */ 313 smu7_read_smc_sram_dword(hwmgr, 314 SMU7_FIRMWARE_HEADER_LOCATION + 315 offsetof(SMU73_Firmware_Header, SoftRegisters), 316 &(priv->smu7_data.soft_regs_start), 0x40000); 317 318 result = smu7_request_smu_load_fw(hwmgr); 319 320 return result; 321 } 322 323 static bool fiji_is_hw_avfs_present(struct pp_hwmgr *hwmgr) 324 { 325 326 uint32_t efuse = 0; 327 uint32_t mask = (1 << ((AVFS_EN_MSB - AVFS_EN_LSB) + 1)) - 1; 328 329 if (!hwmgr->not_vf) 330 return false; 331 332 if (!atomctrl_read_efuse(hwmgr, AVFS_EN_LSB, AVFS_EN_MSB, 333 mask, &efuse)) { 334 if (efuse) 335 return true; 336 } 337 return false; 338 } 339 340 static int fiji_smu_init(struct pp_hwmgr *hwmgr) 341 { 342 struct fiji_smumgr *fiji_priv = NULL; 343 344 fiji_priv = kzalloc(sizeof(struct fiji_smumgr), GFP_KERNEL); 345 346 if (fiji_priv == NULL) 347 return -ENOMEM; 348 349 hwmgr->smu_backend = fiji_priv; 350 351 if (smu7_init(hwmgr)) { 352 kfree(fiji_priv); 353 return -EINVAL; 354 } 355 356 return 0; 357 } 358 359 static int fiji_get_dependency_volt_by_clk(struct pp_hwmgr *hwmgr, 360 struct phm_ppt_v1_clock_voltage_dependency_table *dep_table, 361 uint32_t clock, uint32_t *voltage, uint32_t *mvdd) 362 { 363 uint32_t i; 364 uint16_t vddci; 365 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 366 *voltage = *mvdd = 0; 367 368 369 /* clock - voltage dependency table is empty table */ 370 if (dep_table->count == 0) 371 return -EINVAL; 372 373 for (i = 0; i < dep_table->count; i++) { 374 /* find first sclk bigger than request */ 375 if (dep_table->entries[i].clk >= clock) { 376 *voltage |= (dep_table->entries[i].vddc * 377 VOLTAGE_SCALE) << VDDC_SHIFT; 378 if (SMU7_VOLTAGE_CONTROL_NONE == data->vddci_control) 379 *voltage |= (data->vbios_boot_state.vddci_bootup_value * 380 VOLTAGE_SCALE) << VDDCI_SHIFT; 381 else if (dep_table->entries[i].vddci) 382 *voltage |= (dep_table->entries[i].vddci * 383 VOLTAGE_SCALE) << VDDCI_SHIFT; 384 else { 385 vddci = phm_find_closest_vddci(&(data->vddci_voltage_table), 386 (dep_table->entries[i].vddc - 387 VDDC_VDDCI_DELTA)); 388 *voltage |= (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT; 389 } 390 391 if (SMU7_VOLTAGE_CONTROL_NONE == data->mvdd_control) 392 *mvdd = data->vbios_boot_state.mvdd_bootup_value * 393 VOLTAGE_SCALE; 394 else if (dep_table->entries[i].mvdd) 395 *mvdd = (uint32_t) dep_table->entries[i].mvdd * 396 VOLTAGE_SCALE; 397 398 *voltage |= 1 << PHASES_SHIFT; 399 return 0; 400 } 401 } 402 403 /* sclk is bigger than max sclk in the dependence table */ 404 *voltage |= (dep_table->entries[i - 1].vddc * VOLTAGE_SCALE) << VDDC_SHIFT; 405 406 if (SMU7_VOLTAGE_CONTROL_NONE == data->vddci_control) 407 *voltage |= (data->vbios_boot_state.vddci_bootup_value * 408 VOLTAGE_SCALE) << VDDCI_SHIFT; 409 else if (dep_table->entries[i-1].vddci) { 410 vddci = phm_find_closest_vddci(&(data->vddci_voltage_table), 411 (dep_table->entries[i].vddc - 412 VDDC_VDDCI_DELTA)); 413 *voltage |= (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT; 414 } 415 416 if (SMU7_VOLTAGE_CONTROL_NONE == data->mvdd_control) 417 *mvdd = data->vbios_boot_state.mvdd_bootup_value * VOLTAGE_SCALE; 418 else if (dep_table->entries[i].mvdd) 419 *mvdd = (uint32_t) dep_table->entries[i - 1].mvdd * VOLTAGE_SCALE; 420 421 return 0; 422 } 423 424 425 static uint16_t scale_fan_gain_settings(uint16_t raw_setting) 426 { 427 uint32_t tmp; 428 tmp = raw_setting * 4096 / 100; 429 return (uint16_t)tmp; 430 } 431 432 static void get_scl_sda_value(uint8_t line, uint8_t *scl, uint8_t *sda) 433 { 434 switch (line) { 435 case SMU7_I2CLineID_DDC1: 436 *scl = SMU7_I2C_DDC1CLK; 437 *sda = SMU7_I2C_DDC1DATA; 438 break; 439 case SMU7_I2CLineID_DDC2: 440 *scl = SMU7_I2C_DDC2CLK; 441 *sda = SMU7_I2C_DDC2DATA; 442 break; 443 case SMU7_I2CLineID_DDC3: 444 *scl = SMU7_I2C_DDC3CLK; 445 *sda = SMU7_I2C_DDC3DATA; 446 break; 447 case SMU7_I2CLineID_DDC4: 448 *scl = SMU7_I2C_DDC4CLK; 449 *sda = SMU7_I2C_DDC4DATA; 450 break; 451 case SMU7_I2CLineID_DDC5: 452 *scl = SMU7_I2C_DDC5CLK; 453 *sda = SMU7_I2C_DDC5DATA; 454 break; 455 case SMU7_I2CLineID_DDC6: 456 *scl = SMU7_I2C_DDC6CLK; 457 *sda = SMU7_I2C_DDC6DATA; 458 break; 459 case SMU7_I2CLineID_SCLSDA: 460 *scl = SMU7_I2C_SCL; 461 *sda = SMU7_I2C_SDA; 462 break; 463 case SMU7_I2CLineID_DDCVGA: 464 *scl = SMU7_I2C_DDCVGACLK; 465 *sda = SMU7_I2C_DDCVGADATA; 466 break; 467 default: 468 *scl = 0; 469 *sda = 0; 470 break; 471 } 472 } 473 474 static void fiji_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr) 475 { 476 struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); 477 struct phm_ppt_v1_information *table_info = 478 (struct phm_ppt_v1_information *)(hwmgr->pptable); 479 480 if (table_info && 481 table_info->cac_dtp_table->usPowerTuneDataSetID <= POWERTUNE_DEFAULT_SET_MAX && 482 table_info->cac_dtp_table->usPowerTuneDataSetID) 483 smu_data->power_tune_defaults = 484 &fiji_power_tune_data_set_array 485 [table_info->cac_dtp_table->usPowerTuneDataSetID - 1]; 486 else 487 smu_data->power_tune_defaults = &fiji_power_tune_data_set_array[0]; 488 489 } 490 491 static int fiji_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr) 492 { 493 494 struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); 495 const struct fiji_pt_defaults *defaults = smu_data->power_tune_defaults; 496 497 SMU73_Discrete_DpmTable *dpm_table = &(smu_data->smc_state_table); 498 499 struct phm_ppt_v1_information *table_info = 500 (struct phm_ppt_v1_information *)(hwmgr->pptable); 501 struct phm_cac_tdp_table *cac_dtp_table = table_info->cac_dtp_table; 502 struct pp_advance_fan_control_parameters *fan_table = 503 &hwmgr->thermal_controller.advanceFanControlParameters; 504 uint8_t uc_scl, uc_sda; 505 506 /* TDP number of fraction bits are changed from 8 to 7 for Fiji 507 * as requested by SMC team 508 */ 509 dpm_table->DefaultTdp = PP_HOST_TO_SMC_US( 510 (uint16_t)(cac_dtp_table->usTDP * 128)); 511 dpm_table->TargetTdp = PP_HOST_TO_SMC_US( 512 (uint16_t)(cac_dtp_table->usTDP * 128)); 513 514 PP_ASSERT_WITH_CODE(cac_dtp_table->usTargetOperatingTemp <= 255, 515 "Target Operating Temp is out of Range!", 516 ); 517 518 dpm_table->GpuTjMax = (uint8_t)(cac_dtp_table->usTargetOperatingTemp); 519 dpm_table->GpuTjHyst = 8; 520 521 dpm_table->DTEAmbientTempBase = defaults->DTEAmbientTempBase; 522 523 /* The following are for new Fiji Multi-input fan/thermal control */ 524 dpm_table->TemperatureLimitEdge = PP_HOST_TO_SMC_US( 525 cac_dtp_table->usTargetOperatingTemp * 256); 526 dpm_table->TemperatureLimitHotspot = PP_HOST_TO_SMC_US( 527 cac_dtp_table->usTemperatureLimitHotspot * 256); 528 dpm_table->TemperatureLimitLiquid1 = PP_HOST_TO_SMC_US( 529 cac_dtp_table->usTemperatureLimitLiquid1 * 256); 530 dpm_table->TemperatureLimitLiquid2 = PP_HOST_TO_SMC_US( 531 cac_dtp_table->usTemperatureLimitLiquid2 * 256); 532 dpm_table->TemperatureLimitVrVddc = PP_HOST_TO_SMC_US( 533 cac_dtp_table->usTemperatureLimitVrVddc * 256); 534 dpm_table->TemperatureLimitVrMvdd = PP_HOST_TO_SMC_US( 535 cac_dtp_table->usTemperatureLimitVrMvdd * 256); 536 dpm_table->TemperatureLimitPlx = PP_HOST_TO_SMC_US( 537 cac_dtp_table->usTemperatureLimitPlx * 256); 538 539 dpm_table->FanGainEdge = PP_HOST_TO_SMC_US( 540 scale_fan_gain_settings(fan_table->usFanGainEdge)); 541 dpm_table->FanGainHotspot = PP_HOST_TO_SMC_US( 542 scale_fan_gain_settings(fan_table->usFanGainHotspot)); 543 dpm_table->FanGainLiquid = PP_HOST_TO_SMC_US( 544 scale_fan_gain_settings(fan_table->usFanGainLiquid)); 545 dpm_table->FanGainVrVddc = PP_HOST_TO_SMC_US( 546 scale_fan_gain_settings(fan_table->usFanGainVrVddc)); 547 dpm_table->FanGainVrMvdd = PP_HOST_TO_SMC_US( 548 scale_fan_gain_settings(fan_table->usFanGainVrMvdd)); 549 dpm_table->FanGainPlx = PP_HOST_TO_SMC_US( 550 scale_fan_gain_settings(fan_table->usFanGainPlx)); 551 dpm_table->FanGainHbm = PP_HOST_TO_SMC_US( 552 scale_fan_gain_settings(fan_table->usFanGainHbm)); 553 554 dpm_table->Liquid1_I2C_address = cac_dtp_table->ucLiquid1_I2C_address; 555 dpm_table->Liquid2_I2C_address = cac_dtp_table->ucLiquid2_I2C_address; 556 dpm_table->Vr_I2C_address = cac_dtp_table->ucVr_I2C_address; 557 dpm_table->Plx_I2C_address = cac_dtp_table->ucPlx_I2C_address; 558 559 get_scl_sda_value(cac_dtp_table->ucLiquid_I2C_Line, &uc_scl, &uc_sda); 560 dpm_table->Liquid_I2C_LineSCL = uc_scl; 561 dpm_table->Liquid_I2C_LineSDA = uc_sda; 562 563 get_scl_sda_value(cac_dtp_table->ucVr_I2C_Line, &uc_scl, &uc_sda); 564 dpm_table->Vr_I2C_LineSCL = uc_scl; 565 dpm_table->Vr_I2C_LineSDA = uc_sda; 566 567 get_scl_sda_value(cac_dtp_table->ucPlx_I2C_Line, &uc_scl, &uc_sda); 568 dpm_table->Plx_I2C_LineSCL = uc_scl; 569 dpm_table->Plx_I2C_LineSDA = uc_sda; 570 571 return 0; 572 } 573 574 575 static int fiji_populate_svi_load_line(struct pp_hwmgr *hwmgr) 576 { 577 struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); 578 const struct fiji_pt_defaults *defaults = smu_data->power_tune_defaults; 579 580 smu_data->power_tune_table.SviLoadLineEn = defaults->SviLoadLineEn; 581 smu_data->power_tune_table.SviLoadLineVddC = defaults->SviLoadLineVddC; 582 smu_data->power_tune_table.SviLoadLineTrimVddC = 3; 583 smu_data->power_tune_table.SviLoadLineOffsetVddC = 0; 584 585 return 0; 586 } 587 588 589 static int fiji_populate_tdc_limit(struct pp_hwmgr *hwmgr) 590 { 591 uint16_t tdc_limit; 592 struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); 593 struct phm_ppt_v1_information *table_info = 594 (struct phm_ppt_v1_information *)(hwmgr->pptable); 595 const struct fiji_pt_defaults *defaults = smu_data->power_tune_defaults; 596 597 /* TDC number of fraction bits are changed from 8 to 7 598 * for Fiji as requested by SMC team 599 */ 600 tdc_limit = (uint16_t)(table_info->cac_dtp_table->usTDC * 128); 601 smu_data->power_tune_table.TDC_VDDC_PkgLimit = 602 CONVERT_FROM_HOST_TO_SMC_US(tdc_limit); 603 smu_data->power_tune_table.TDC_VDDC_ThrottleReleaseLimitPerc = 604 defaults->TDC_VDDC_ThrottleReleaseLimitPerc; 605 smu_data->power_tune_table.TDC_MAWt = defaults->TDC_MAWt; 606 607 return 0; 608 } 609 610 static int fiji_populate_dw8(struct pp_hwmgr *hwmgr, uint32_t fuse_table_offset) 611 { 612 struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); 613 const struct fiji_pt_defaults *defaults = smu_data->power_tune_defaults; 614 uint32_t temp; 615 616 if (smu7_read_smc_sram_dword(hwmgr, 617 fuse_table_offset + 618 offsetof(SMU73_Discrete_PmFuses, TdcWaterfallCtl), 619 (uint32_t *)&temp, SMC_RAM_END)) 620 PP_ASSERT_WITH_CODE(false, 621 "Attempt to read PmFuses.DW6 (SviLoadLineEn) from SMC Failed!", 622 return -EINVAL); 623 else { 624 smu_data->power_tune_table.TdcWaterfallCtl = defaults->TdcWaterfallCtl; 625 smu_data->power_tune_table.LPMLTemperatureMin = 626 (uint8_t)((temp >> 16) & 0xff); 627 smu_data->power_tune_table.LPMLTemperatureMax = 628 (uint8_t)((temp >> 8) & 0xff); 629 smu_data->power_tune_table.Reserved = (uint8_t)(temp & 0xff); 630 } 631 return 0; 632 } 633 634 static int fiji_populate_temperature_scaler(struct pp_hwmgr *hwmgr) 635 { 636 int i; 637 struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); 638 639 /* Currently not used. Set all to zero. */ 640 for (i = 0; i < 16; i++) 641 smu_data->power_tune_table.LPMLTemperatureScaler[i] = 0; 642 643 return 0; 644 } 645 646 static int fiji_populate_fuzzy_fan(struct pp_hwmgr *hwmgr) 647 { 648 struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); 649 650 if ((hwmgr->thermal_controller.advanceFanControlParameters. 651 usFanOutputSensitivity & (1 << 15)) || 652 0 == hwmgr->thermal_controller.advanceFanControlParameters. 653 usFanOutputSensitivity) 654 hwmgr->thermal_controller.advanceFanControlParameters. 655 usFanOutputSensitivity = hwmgr->thermal_controller. 656 advanceFanControlParameters.usDefaultFanOutputSensitivity; 657 658 smu_data->power_tune_table.FuzzyFan_PwmSetDelta = 659 PP_HOST_TO_SMC_US(hwmgr->thermal_controller. 660 advanceFanControlParameters.usFanOutputSensitivity); 661 return 0; 662 } 663 664 static int fiji_populate_gnb_lpml(struct pp_hwmgr *hwmgr) 665 { 666 int i; 667 struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); 668 669 /* Currently not used. Set all to zero. */ 670 for (i = 0; i < 16; i++) 671 smu_data->power_tune_table.GnbLPML[i] = 0; 672 673 return 0; 674 } 675 676 static int fiji_populate_bapm_vddc_base_leakage_sidd(struct pp_hwmgr *hwmgr) 677 { 678 struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); 679 struct phm_ppt_v1_information *table_info = 680 (struct phm_ppt_v1_information *)(hwmgr->pptable); 681 uint16_t HiSidd = smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd; 682 uint16_t LoSidd = smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd; 683 struct phm_cac_tdp_table *cac_table = table_info->cac_dtp_table; 684 685 HiSidd = (uint16_t)(cac_table->usHighCACLeakage / 100 * 256); 686 LoSidd = (uint16_t)(cac_table->usLowCACLeakage / 100 * 256); 687 688 smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd = 689 CONVERT_FROM_HOST_TO_SMC_US(HiSidd); 690 smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd = 691 CONVERT_FROM_HOST_TO_SMC_US(LoSidd); 692 693 return 0; 694 } 695 696 static int fiji_populate_pm_fuses(struct pp_hwmgr *hwmgr) 697 { 698 uint32_t pm_fuse_table_offset; 699 struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); 700 701 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, 702 PHM_PlatformCaps_PowerContainment)) { 703 if (smu7_read_smc_sram_dword(hwmgr, 704 SMU7_FIRMWARE_HEADER_LOCATION + 705 offsetof(SMU73_Firmware_Header, PmFuseTable), 706 &pm_fuse_table_offset, SMC_RAM_END)) 707 PP_ASSERT_WITH_CODE(false, 708 "Attempt to get pm_fuse_table_offset Failed!", 709 return -EINVAL); 710 711 /* DW6 */ 712 if (fiji_populate_svi_load_line(hwmgr)) 713 PP_ASSERT_WITH_CODE(false, 714 "Attempt to populate SviLoadLine Failed!", 715 return -EINVAL); 716 /* DW7 */ 717 if (fiji_populate_tdc_limit(hwmgr)) 718 PP_ASSERT_WITH_CODE(false, 719 "Attempt to populate TDCLimit Failed!", return -EINVAL); 720 /* DW8 */ 721 if (fiji_populate_dw8(hwmgr, pm_fuse_table_offset)) 722 PP_ASSERT_WITH_CODE(false, 723 "Attempt to populate TdcWaterfallCtl, " 724 "LPMLTemperature Min and Max Failed!", 725 return -EINVAL); 726 727 /* DW9-DW12 */ 728 if (0 != fiji_populate_temperature_scaler(hwmgr)) 729 PP_ASSERT_WITH_CODE(false, 730 "Attempt to populate LPMLTemperatureScaler Failed!", 731 return -EINVAL); 732 733 /* DW13-DW14 */ 734 if (fiji_populate_fuzzy_fan(hwmgr)) 735 PP_ASSERT_WITH_CODE(false, 736 "Attempt to populate Fuzzy Fan Control parameters Failed!", 737 return -EINVAL); 738 739 /* DW15-DW18 */ 740 if (fiji_populate_gnb_lpml(hwmgr)) 741 PP_ASSERT_WITH_CODE(false, 742 "Attempt to populate GnbLPML Failed!", 743 return -EINVAL); 744 745 /* DW20 */ 746 if (fiji_populate_bapm_vddc_base_leakage_sidd(hwmgr)) 747 PP_ASSERT_WITH_CODE(false, 748 "Attempt to populate BapmVddCBaseLeakage Hi and Lo " 749 "Sidd Failed!", return -EINVAL); 750 751 if (smu7_copy_bytes_to_smc(hwmgr, pm_fuse_table_offset, 752 (uint8_t *)&smu_data->power_tune_table, 753 sizeof(struct SMU73_Discrete_PmFuses), SMC_RAM_END)) 754 PP_ASSERT_WITH_CODE(false, 755 "Attempt to download PmFuseTable Failed!", 756 return -EINVAL); 757 } 758 return 0; 759 } 760 761 static int fiji_populate_cac_table(struct pp_hwmgr *hwmgr, 762 struct SMU73_Discrete_DpmTable *table) 763 { 764 uint32_t count; 765 uint8_t index; 766 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 767 struct phm_ppt_v1_information *table_info = 768 (struct phm_ppt_v1_information *)(hwmgr->pptable); 769 struct phm_ppt_v1_voltage_lookup_table *lookup_table = 770 table_info->vddc_lookup_table; 771 /* tables is already swapped, so in order to use the value from it, 772 * we need to swap it back. 773 * We are populating vddc CAC data to BapmVddc table 774 * in split and merged mode 775 */ 776 777 for (count = 0; count < lookup_table->count; count++) { 778 index = phm_get_voltage_index(lookup_table, 779 data->vddc_voltage_table.entries[count].value); 780 table->BapmVddcVidLoSidd[count] = 781 convert_to_vid(lookup_table->entries[index].us_cac_low); 782 table->BapmVddcVidHiSidd[count] = 783 convert_to_vid(lookup_table->entries[index].us_cac_high); 784 } 785 786 return 0; 787 } 788 789 static int fiji_populate_smc_voltage_tables(struct pp_hwmgr *hwmgr, 790 struct SMU73_Discrete_DpmTable *table) 791 { 792 int result; 793 794 result = fiji_populate_cac_table(hwmgr, table); 795 PP_ASSERT_WITH_CODE(0 == result, 796 "can not populate CAC voltage tables to SMC", 797 return -EINVAL); 798 799 return 0; 800 } 801 802 static int fiji_populate_ulv_level(struct pp_hwmgr *hwmgr, 803 struct SMU73_Discrete_Ulv *state) 804 { 805 int result = 0; 806 807 struct phm_ppt_v1_information *table_info = 808 (struct phm_ppt_v1_information *)(hwmgr->pptable); 809 810 state->CcPwrDynRm = 0; 811 state->CcPwrDynRm1 = 0; 812 813 state->VddcOffset = (uint16_t) table_info->us_ulv_voltage_offset; 814 state->VddcOffsetVid = (uint8_t)(table_info->us_ulv_voltage_offset * 815 VOLTAGE_VID_OFFSET_SCALE2 / VOLTAGE_VID_OFFSET_SCALE1); 816 817 state->VddcPhase = 1; 818 819 if (!result) { 820 CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm); 821 CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm1); 822 CONVERT_FROM_HOST_TO_SMC_US(state->VddcOffset); 823 } 824 return result; 825 } 826 827 static int fiji_populate_ulv_state(struct pp_hwmgr *hwmgr, 828 struct SMU73_Discrete_DpmTable *table) 829 { 830 return fiji_populate_ulv_level(hwmgr, &table->Ulv); 831 } 832 833 static int fiji_populate_smc_link_level(struct pp_hwmgr *hwmgr, 834 struct SMU73_Discrete_DpmTable *table) 835 { 836 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 837 struct smu7_dpm_table *dpm_table = &data->dpm_table; 838 struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); 839 int i; 840 841 /* Index (dpm_table->pcie_speed_table.count) 842 * is reserved for PCIE boot level. */ 843 for (i = 0; i <= dpm_table->pcie_speed_table.count; i++) { 844 table->LinkLevel[i].PcieGenSpeed = 845 (uint8_t)dpm_table->pcie_speed_table.dpm_levels[i].value; 846 table->LinkLevel[i].PcieLaneCount = (uint8_t)encode_pcie_lane_width( 847 dpm_table->pcie_speed_table.dpm_levels[i].param1); 848 table->LinkLevel[i].EnabledForActivity = 1; 849 table->LinkLevel[i].SPC = (uint8_t)(data->pcie_spc_cap & 0xff); 850 table->LinkLevel[i].DownThreshold = PP_HOST_TO_SMC_UL(5); 851 table->LinkLevel[i].UpThreshold = PP_HOST_TO_SMC_UL(30); 852 } 853 854 smu_data->smc_state_table.LinkLevelCount = 855 (uint8_t)dpm_table->pcie_speed_table.count; 856 data->dpm_level_enable_mask.pcie_dpm_enable_mask = 857 phm_get_dpm_level_enable_mask_value(&dpm_table->pcie_speed_table); 858 859 return 0; 860 } 861 862 static int fiji_calculate_sclk_params(struct pp_hwmgr *hwmgr, 863 uint32_t clock, struct SMU73_Discrete_GraphicsLevel *sclk) 864 { 865 const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 866 struct pp_atomctrl_clock_dividers_vi dividers; 867 uint32_t spll_func_cntl = data->clock_registers.vCG_SPLL_FUNC_CNTL; 868 uint32_t spll_func_cntl_3 = data->clock_registers.vCG_SPLL_FUNC_CNTL_3; 869 uint32_t spll_func_cntl_4 = data->clock_registers.vCG_SPLL_FUNC_CNTL_4; 870 uint32_t cg_spll_spread_spectrum = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM; 871 uint32_t cg_spll_spread_spectrum_2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2; 872 uint32_t ref_clock; 873 uint32_t ref_divider; 874 uint32_t fbdiv; 875 int result; 876 877 /* get the engine clock dividers for this clock value */ 878 result = atomctrl_get_engine_pll_dividers_vi(hwmgr, clock, ÷rs); 879 880 PP_ASSERT_WITH_CODE(result == 0, 881 "Error retrieving Engine Clock dividers from VBIOS.", 882 return result); 883 884 /* To get FBDIV we need to multiply this by 16384 and divide it by Fref. */ 885 ref_clock = atomctrl_get_reference_clock(hwmgr); 886 ref_divider = 1 + dividers.uc_pll_ref_div; 887 888 /* low 14 bits is fraction and high 12 bits is divider */ 889 fbdiv = dividers.ul_fb_div.ul_fb_divider & 0x3FFFFFF; 890 891 /* SPLL_FUNC_CNTL setup */ 892 spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, CG_SPLL_FUNC_CNTL, 893 SPLL_REF_DIV, dividers.uc_pll_ref_div); 894 spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, CG_SPLL_FUNC_CNTL, 895 SPLL_PDIV_A, dividers.uc_pll_post_div); 896 897 /* SPLL_FUNC_CNTL_3 setup*/ 898 spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3, CG_SPLL_FUNC_CNTL_3, 899 SPLL_FB_DIV, fbdiv); 900 901 /* set to use fractional accumulation*/ 902 spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3, CG_SPLL_FUNC_CNTL_3, 903 SPLL_DITHEN, 1); 904 905 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, 906 PHM_PlatformCaps_EngineSpreadSpectrumSupport)) { 907 struct pp_atomctrl_internal_ss_info ssInfo; 908 909 uint32_t vco_freq = clock * dividers.uc_pll_post_div; 910 if (!atomctrl_get_engine_clock_spread_spectrum(hwmgr, 911 vco_freq, &ssInfo)) { 912 /* 913 * ss_info.speed_spectrum_percentage -- in unit of 0.01% 914 * ss_info.speed_spectrum_rate -- in unit of khz 915 * 916 * clks = reference_clock * 10 / (REFDIV + 1) / speed_spectrum_rate / 2 917 */ 918 uint32_t clk_s = ref_clock * 5 / 919 (ref_divider * ssInfo.speed_spectrum_rate); 920 /* clkv = 2 * D * fbdiv / NS */ 921 uint32_t clk_v = 4 * ssInfo.speed_spectrum_percentage * 922 fbdiv / (clk_s * 10000); 923 924 cg_spll_spread_spectrum = PHM_SET_FIELD(cg_spll_spread_spectrum, 925 CG_SPLL_SPREAD_SPECTRUM, CLKS, clk_s); 926 cg_spll_spread_spectrum = PHM_SET_FIELD(cg_spll_spread_spectrum, 927 CG_SPLL_SPREAD_SPECTRUM, SSEN, 1); 928 cg_spll_spread_spectrum_2 = PHM_SET_FIELD(cg_spll_spread_spectrum_2, 929 CG_SPLL_SPREAD_SPECTRUM_2, CLKV, clk_v); 930 } 931 } 932 933 sclk->SclkFrequency = clock; 934 sclk->CgSpllFuncCntl3 = spll_func_cntl_3; 935 sclk->CgSpllFuncCntl4 = spll_func_cntl_4; 936 sclk->SpllSpreadSpectrum = cg_spll_spread_spectrum; 937 sclk->SpllSpreadSpectrum2 = cg_spll_spread_spectrum_2; 938 sclk->SclkDid = (uint8_t)dividers.pll_post_divider; 939 940 return 0; 941 } 942 943 static int fiji_populate_single_graphic_level(struct pp_hwmgr *hwmgr, 944 uint32_t clock, struct SMU73_Discrete_GraphicsLevel *level) 945 { 946 int result; 947 /* PP_Clocks minClocks; */ 948 uint32_t mvdd; 949 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 950 struct phm_ppt_v1_information *table_info = 951 (struct phm_ppt_v1_information *)(hwmgr->pptable); 952 phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_table = NULL; 953 954 result = fiji_calculate_sclk_params(hwmgr, clock, level); 955 956 if (hwmgr->od_enabled) 957 vdd_dep_table = (phm_ppt_v1_clock_voltage_dependency_table *)&data->odn_dpm_table.vdd_dependency_on_sclk; 958 else 959 vdd_dep_table = table_info->vdd_dep_on_sclk; 960 961 /* populate graphics levels */ 962 result = fiji_get_dependency_volt_by_clk(hwmgr, 963 vdd_dep_table, clock, 964 (uint32_t *)(&level->MinVoltage), &mvdd); 965 PP_ASSERT_WITH_CODE((0 == result), 966 "can not find VDDC voltage value for " 967 "VDDC engine clock dependency table", 968 return result); 969 970 level->SclkFrequency = clock; 971 level->ActivityLevel = data->current_profile_setting.sclk_activity; 972 level->CcPwrDynRm = 0; 973 level->CcPwrDynRm1 = 0; 974 level->EnabledForActivity = 0; 975 level->EnabledForThrottle = 1; 976 level->UpHyst = data->current_profile_setting.sclk_up_hyst; 977 level->DownHyst = data->current_profile_setting.sclk_down_hyst; 978 level->VoltageDownHyst = 0; 979 level->PowerThrottle = 0; 980 981 data->display_timing.min_clock_in_sr = hwmgr->display_config->min_core_set_clock_in_sr; 982 983 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep)) 984 level->DeepSleepDivId = smu7_get_sleep_divider_id_from_clock(clock, 985 hwmgr->display_config->min_core_set_clock_in_sr); 986 987 988 /* Default to slow, highest DPM level will be 989 * set to PPSMC_DISPLAY_WATERMARK_LOW later. 990 */ 991 level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; 992 993 CONVERT_FROM_HOST_TO_SMC_UL(level->MinVoltage); 994 CONVERT_FROM_HOST_TO_SMC_UL(level->SclkFrequency); 995 CONVERT_FROM_HOST_TO_SMC_US(level->ActivityLevel); 996 CONVERT_FROM_HOST_TO_SMC_UL(level->CgSpllFuncCntl3); 997 CONVERT_FROM_HOST_TO_SMC_UL(level->CgSpllFuncCntl4); 998 CONVERT_FROM_HOST_TO_SMC_UL(level->SpllSpreadSpectrum); 999 CONVERT_FROM_HOST_TO_SMC_UL(level->SpllSpreadSpectrum2); 1000 CONVERT_FROM_HOST_TO_SMC_UL(level->CcPwrDynRm); 1001 CONVERT_FROM_HOST_TO_SMC_UL(level->CcPwrDynRm1); 1002 1003 return 0; 1004 } 1005 1006 static int fiji_populate_all_graphic_levels(struct pp_hwmgr *hwmgr) 1007 { 1008 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 1009 struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); 1010 1011 struct smu7_dpm_table *dpm_table = &data->dpm_table; 1012 struct phm_ppt_v1_information *table_info = 1013 (struct phm_ppt_v1_information *)(hwmgr->pptable); 1014 struct phm_ppt_v1_pcie_table *pcie_table = table_info->pcie_table; 1015 uint8_t pcie_entry_cnt = (uint8_t) data->dpm_table.pcie_speed_table.count; 1016 int result = 0; 1017 uint32_t array = smu_data->smu7_data.dpm_table_start + 1018 offsetof(SMU73_Discrete_DpmTable, GraphicsLevel); 1019 uint32_t array_size = sizeof(struct SMU73_Discrete_GraphicsLevel) * 1020 SMU73_MAX_LEVELS_GRAPHICS; 1021 struct SMU73_Discrete_GraphicsLevel *levels = 1022 smu_data->smc_state_table.GraphicsLevel; 1023 uint32_t i, max_entry; 1024 uint8_t hightest_pcie_level_enabled = 0, 1025 lowest_pcie_level_enabled = 0, 1026 mid_pcie_level_enabled = 0, 1027 count = 0; 1028 1029 for (i = 0; i < dpm_table->sclk_table.count; i++) { 1030 result = fiji_populate_single_graphic_level(hwmgr, 1031 dpm_table->sclk_table.dpm_levels[i].value, 1032 &levels[i]); 1033 if (result) 1034 return result; 1035 1036 /* Making sure only DPM level 0-1 have Deep Sleep Div ID populated. */ 1037 if (i > 1) 1038 levels[i].DeepSleepDivId = 0; 1039 } 1040 1041 /* Only enable level 0 for now.*/ 1042 levels[0].EnabledForActivity = 1; 1043 1044 /* set highest level watermark to high */ 1045 levels[dpm_table->sclk_table.count - 1].DisplayWatermark = 1046 PPSMC_DISPLAY_WATERMARK_HIGH; 1047 1048 smu_data->smc_state_table.GraphicsDpmLevelCount = 1049 (uint8_t)dpm_table->sclk_table.count; 1050 data->dpm_level_enable_mask.sclk_dpm_enable_mask = 1051 phm_get_dpm_level_enable_mask_value(&dpm_table->sclk_table); 1052 1053 if (pcie_table != NULL) { 1054 PP_ASSERT_WITH_CODE((1 <= pcie_entry_cnt), 1055 "There must be 1 or more PCIE levels defined in PPTable.", 1056 return -EINVAL); 1057 max_entry = pcie_entry_cnt - 1; 1058 for (i = 0; i < dpm_table->sclk_table.count; i++) 1059 levels[i].pcieDpmLevel = 1060 (uint8_t) ((i < max_entry) ? i : max_entry); 1061 } else { 1062 while (data->dpm_level_enable_mask.pcie_dpm_enable_mask && 1063 ((data->dpm_level_enable_mask.pcie_dpm_enable_mask & 1064 (1 << (hightest_pcie_level_enabled + 1))) != 0)) 1065 hightest_pcie_level_enabled++; 1066 1067 while (data->dpm_level_enable_mask.pcie_dpm_enable_mask && 1068 ((data->dpm_level_enable_mask.pcie_dpm_enable_mask & 1069 (1 << lowest_pcie_level_enabled)) == 0)) 1070 lowest_pcie_level_enabled++; 1071 1072 while ((count < hightest_pcie_level_enabled) && 1073 ((data->dpm_level_enable_mask.pcie_dpm_enable_mask & 1074 (1 << (lowest_pcie_level_enabled + 1 + count))) == 0)) 1075 count++; 1076 1077 mid_pcie_level_enabled = (lowest_pcie_level_enabled + 1 + count) < 1078 hightest_pcie_level_enabled ? 1079 (lowest_pcie_level_enabled + 1 + count) : 1080 hightest_pcie_level_enabled; 1081 1082 /* set pcieDpmLevel to hightest_pcie_level_enabled */ 1083 for (i = 2; i < dpm_table->sclk_table.count; i++) 1084 levels[i].pcieDpmLevel = hightest_pcie_level_enabled; 1085 1086 /* set pcieDpmLevel to lowest_pcie_level_enabled */ 1087 levels[0].pcieDpmLevel = lowest_pcie_level_enabled; 1088 1089 /* set pcieDpmLevel to mid_pcie_level_enabled */ 1090 levels[1].pcieDpmLevel = mid_pcie_level_enabled; 1091 } 1092 /* level count will send to smc once at init smc table and never change */ 1093 result = smu7_copy_bytes_to_smc(hwmgr, array, (uint8_t *)levels, 1094 (uint32_t)array_size, SMC_RAM_END); 1095 1096 return result; 1097 } 1098 1099 1100 /** 1101 * MCLK Frequency Ratio 1102 * SEQ_CG_RESP Bit[31:24] - 0x0 1103 * Bit[27:24] \96 DDR3 Frequency ratio 1104 * 0x0 <= 100MHz, 450 < 0x8 <= 500MHz 1105 * 100 < 0x1 <= 150MHz, 500 < 0x9 <= 550MHz 1106 * 150 < 0x2 <= 200MHz, 550 < 0xA <= 600MHz 1107 * 200 < 0x3 <= 250MHz, 600 < 0xB <= 650MHz 1108 * 250 < 0x4 <= 300MHz, 650 < 0xC <= 700MHz 1109 * 300 < 0x5 <= 350MHz, 700 < 0xD <= 750MHz 1110 * 350 < 0x6 <= 400MHz, 750 < 0xE <= 800MHz 1111 * 400 < 0x7 <= 450MHz, 800 < 0xF 1112 */ 1113 static uint8_t fiji_get_mclk_frequency_ratio(uint32_t mem_clock) 1114 { 1115 if (mem_clock <= 10000) 1116 return 0x0; 1117 if (mem_clock <= 15000) 1118 return 0x1; 1119 if (mem_clock <= 20000) 1120 return 0x2; 1121 if (mem_clock <= 25000) 1122 return 0x3; 1123 if (mem_clock <= 30000) 1124 return 0x4; 1125 if (mem_clock <= 35000) 1126 return 0x5; 1127 if (mem_clock <= 40000) 1128 return 0x6; 1129 if (mem_clock <= 45000) 1130 return 0x7; 1131 if (mem_clock <= 50000) 1132 return 0x8; 1133 if (mem_clock <= 55000) 1134 return 0x9; 1135 if (mem_clock <= 60000) 1136 return 0xa; 1137 if (mem_clock <= 65000) 1138 return 0xb; 1139 if (mem_clock <= 70000) 1140 return 0xc; 1141 if (mem_clock <= 75000) 1142 return 0xd; 1143 if (mem_clock <= 80000) 1144 return 0xe; 1145 /* mem_clock > 800MHz */ 1146 return 0xf; 1147 } 1148 1149 static int fiji_calculate_mclk_params(struct pp_hwmgr *hwmgr, 1150 uint32_t clock, struct SMU73_Discrete_MemoryLevel *mclk) 1151 { 1152 struct pp_atomctrl_memory_clock_param mem_param; 1153 int result; 1154 1155 result = atomctrl_get_memory_pll_dividers_vi(hwmgr, clock, &mem_param); 1156 PP_ASSERT_WITH_CODE((0 == result), 1157 "Failed to get Memory PLL Dividers.", 1158 ); 1159 1160 /* Save the result data to outpupt memory level structure */ 1161 mclk->MclkFrequency = clock; 1162 mclk->MclkDivider = (uint8_t)mem_param.mpll_post_divider; 1163 mclk->FreqRange = fiji_get_mclk_frequency_ratio(clock); 1164 1165 return result; 1166 } 1167 1168 static int fiji_populate_single_memory_level(struct pp_hwmgr *hwmgr, 1169 uint32_t clock, struct SMU73_Discrete_MemoryLevel *mem_level) 1170 { 1171 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 1172 struct phm_ppt_v1_information *table_info = 1173 (struct phm_ppt_v1_information *)(hwmgr->pptable); 1174 int result = 0; 1175 uint32_t mclk_stutter_mode_threshold = 60000; 1176 phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_table = NULL; 1177 1178 if (hwmgr->od_enabled) 1179 vdd_dep_table = (phm_ppt_v1_clock_voltage_dependency_table *)&data->odn_dpm_table.vdd_dependency_on_mclk; 1180 else 1181 vdd_dep_table = table_info->vdd_dep_on_mclk; 1182 1183 if (vdd_dep_table) { 1184 result = fiji_get_dependency_volt_by_clk(hwmgr, 1185 vdd_dep_table, clock, 1186 (uint32_t *)(&mem_level->MinVoltage), &mem_level->MinMvdd); 1187 PP_ASSERT_WITH_CODE((0 == result), 1188 "can not find MinVddc voltage value from memory " 1189 "VDDC voltage dependency table", return result); 1190 } 1191 1192 mem_level->EnabledForThrottle = 1; 1193 mem_level->EnabledForActivity = 0; 1194 mem_level->UpHyst = data->current_profile_setting.mclk_up_hyst; 1195 mem_level->DownHyst = data->current_profile_setting.mclk_down_hyst; 1196 mem_level->VoltageDownHyst = 0; 1197 mem_level->ActivityLevel = data->current_profile_setting.mclk_activity; 1198 mem_level->StutterEnable = false; 1199 1200 mem_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; 1201 1202 /* enable stutter mode if all the follow condition applied 1203 * PECI_GetNumberOfActiveDisplays(hwmgr->pPECI, 1204 * &(data->DisplayTiming.numExistingDisplays)); 1205 */ 1206 data->display_timing.num_existing_displays = hwmgr->display_config->num_display; 1207 data->display_timing.vrefresh = hwmgr->display_config->vrefresh; 1208 1209 if (mclk_stutter_mode_threshold && 1210 (clock <= mclk_stutter_mode_threshold) && 1211 (!data->is_uvd_enabled) && 1212 (PHM_READ_FIELD(hwmgr->device, DPG_PIPE_STUTTER_CONTROL, 1213 STUTTER_ENABLE) & 0x1)) 1214 mem_level->StutterEnable = true; 1215 1216 result = fiji_calculate_mclk_params(hwmgr, clock, mem_level); 1217 if (!result) { 1218 CONVERT_FROM_HOST_TO_SMC_UL(mem_level->MinMvdd); 1219 CONVERT_FROM_HOST_TO_SMC_UL(mem_level->MclkFrequency); 1220 CONVERT_FROM_HOST_TO_SMC_US(mem_level->ActivityLevel); 1221 CONVERT_FROM_HOST_TO_SMC_UL(mem_level->MinVoltage); 1222 } 1223 return result; 1224 } 1225 1226 static int fiji_populate_all_memory_levels(struct pp_hwmgr *hwmgr) 1227 { 1228 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 1229 struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); 1230 struct smu7_dpm_table *dpm_table = &data->dpm_table; 1231 int result; 1232 /* populate MCLK dpm table to SMU7 */ 1233 uint32_t array = smu_data->smu7_data.dpm_table_start + 1234 offsetof(SMU73_Discrete_DpmTable, MemoryLevel); 1235 uint32_t array_size = sizeof(SMU73_Discrete_MemoryLevel) * 1236 SMU73_MAX_LEVELS_MEMORY; 1237 struct SMU73_Discrete_MemoryLevel *levels = 1238 smu_data->smc_state_table.MemoryLevel; 1239 uint32_t i; 1240 1241 for (i = 0; i < dpm_table->mclk_table.count; i++) { 1242 PP_ASSERT_WITH_CODE((0 != dpm_table->mclk_table.dpm_levels[i].value), 1243 "can not populate memory level as memory clock is zero", 1244 return -EINVAL); 1245 result = fiji_populate_single_memory_level(hwmgr, 1246 dpm_table->mclk_table.dpm_levels[i].value, 1247 &levels[i]); 1248 if (result) 1249 return result; 1250 } 1251 1252 /* Only enable level 0 for now. */ 1253 levels[0].EnabledForActivity = 1; 1254 1255 /* in order to prevent MC activity from stutter mode to push DPM up. 1256 * the UVD change complements this by putting the MCLK in 1257 * a higher state by default such that we are not effected by 1258 * up threshold or and MCLK DPM latency. 1259 */ 1260 levels[0].ActivityLevel = (uint16_t)data->mclk_dpm0_activity_target; 1261 CONVERT_FROM_HOST_TO_SMC_US(levels[0].ActivityLevel); 1262 1263 smu_data->smc_state_table.MemoryDpmLevelCount = 1264 (uint8_t)dpm_table->mclk_table.count; 1265 data->dpm_level_enable_mask.mclk_dpm_enable_mask = 1266 phm_get_dpm_level_enable_mask_value(&dpm_table->mclk_table); 1267 /* set highest level watermark to high */ 1268 levels[dpm_table->mclk_table.count - 1].DisplayWatermark = 1269 PPSMC_DISPLAY_WATERMARK_HIGH; 1270 1271 /* level count will send to smc once at init smc table and never change */ 1272 result = smu7_copy_bytes_to_smc(hwmgr, array, (uint8_t *)levels, 1273 (uint32_t)array_size, SMC_RAM_END); 1274 1275 return result; 1276 } 1277 1278 static int fiji_populate_mvdd_value(struct pp_hwmgr *hwmgr, 1279 uint32_t mclk, SMIO_Pattern *smio_pat) 1280 { 1281 const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 1282 struct phm_ppt_v1_information *table_info = 1283 (struct phm_ppt_v1_information *)(hwmgr->pptable); 1284 uint32_t i = 0; 1285 1286 if (SMU7_VOLTAGE_CONTROL_NONE != data->mvdd_control) { 1287 /* find mvdd value which clock is more than request */ 1288 for (i = 0; i < table_info->vdd_dep_on_mclk->count; i++) { 1289 if (mclk <= table_info->vdd_dep_on_mclk->entries[i].clk) { 1290 smio_pat->Voltage = data->mvdd_voltage_table.entries[i].value; 1291 break; 1292 } 1293 } 1294 PP_ASSERT_WITH_CODE(i < table_info->vdd_dep_on_mclk->count, 1295 "MVDD Voltage is outside the supported range.", 1296 return -EINVAL); 1297 } else 1298 return -EINVAL; 1299 1300 return 0; 1301 } 1302 1303 static int fiji_populate_smc_acpi_level(struct pp_hwmgr *hwmgr, 1304 SMU73_Discrete_DpmTable *table) 1305 { 1306 int result = 0; 1307 const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 1308 struct phm_ppt_v1_information *table_info = 1309 (struct phm_ppt_v1_information *)(hwmgr->pptable); 1310 struct pp_atomctrl_clock_dividers_vi dividers; 1311 SMIO_Pattern vol_level; 1312 uint32_t mvdd; 1313 uint16_t us_mvdd; 1314 uint32_t spll_func_cntl = data->clock_registers.vCG_SPLL_FUNC_CNTL; 1315 uint32_t spll_func_cntl_2 = data->clock_registers.vCG_SPLL_FUNC_CNTL_2; 1316 1317 table->ACPILevel.Flags &= ~PPSMC_SWSTATE_FLAG_DC; 1318 1319 if (!data->sclk_dpm_key_disabled) { 1320 /* Get MinVoltage and Frequency from DPM0, 1321 * already converted to SMC_UL */ 1322 table->ACPILevel.SclkFrequency = 1323 data->dpm_table.sclk_table.dpm_levels[0].value; 1324 result = fiji_get_dependency_volt_by_clk(hwmgr, 1325 table_info->vdd_dep_on_sclk, 1326 table->ACPILevel.SclkFrequency, 1327 (uint32_t *)(&table->ACPILevel.MinVoltage), &mvdd); 1328 PP_ASSERT_WITH_CODE((0 == result), 1329 "Cannot find ACPI VDDC voltage value " \ 1330 "in Clock Dependency Table", 1331 ); 1332 } else { 1333 table->ACPILevel.SclkFrequency = 1334 data->vbios_boot_state.sclk_bootup_value; 1335 table->ACPILevel.MinVoltage = 1336 data->vbios_boot_state.vddc_bootup_value * VOLTAGE_SCALE; 1337 } 1338 1339 /* get the engine clock dividers for this clock value */ 1340 result = atomctrl_get_engine_pll_dividers_vi(hwmgr, 1341 table->ACPILevel.SclkFrequency, ÷rs); 1342 PP_ASSERT_WITH_CODE(result == 0, 1343 "Error retrieving Engine Clock dividers from VBIOS.", 1344 return result); 1345 1346 table->ACPILevel.SclkDid = (uint8_t)dividers.pll_post_divider; 1347 table->ACPILevel.DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; 1348 table->ACPILevel.DeepSleepDivId = 0; 1349 1350 spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, CG_SPLL_FUNC_CNTL, 1351 SPLL_PWRON, 0); 1352 spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, CG_SPLL_FUNC_CNTL, 1353 SPLL_RESET, 1); 1354 spll_func_cntl_2 = PHM_SET_FIELD(spll_func_cntl_2, CG_SPLL_FUNC_CNTL_2, 1355 SCLK_MUX_SEL, 4); 1356 1357 table->ACPILevel.CgSpllFuncCntl = spll_func_cntl; 1358 table->ACPILevel.CgSpllFuncCntl2 = spll_func_cntl_2; 1359 table->ACPILevel.CgSpllFuncCntl3 = data->clock_registers.vCG_SPLL_FUNC_CNTL_3; 1360 table->ACPILevel.CgSpllFuncCntl4 = data->clock_registers.vCG_SPLL_FUNC_CNTL_4; 1361 table->ACPILevel.SpllSpreadSpectrum = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM; 1362 table->ACPILevel.SpllSpreadSpectrum2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2; 1363 table->ACPILevel.CcPwrDynRm = 0; 1364 table->ACPILevel.CcPwrDynRm1 = 0; 1365 1366 CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.Flags); 1367 CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SclkFrequency); 1368 CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.MinVoltage); 1369 CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl); 1370 CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl2); 1371 CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl3); 1372 CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl4); 1373 CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum); 1374 CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum2); 1375 CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm); 1376 CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm1); 1377 1378 if (!data->mclk_dpm_key_disabled) { 1379 /* Get MinVoltage and Frequency from DPM0, already converted to SMC_UL */ 1380 table->MemoryACPILevel.MclkFrequency = 1381 data->dpm_table.mclk_table.dpm_levels[0].value; 1382 result = fiji_get_dependency_volt_by_clk(hwmgr, 1383 table_info->vdd_dep_on_mclk, 1384 table->MemoryACPILevel.MclkFrequency, 1385 (uint32_t *)(&table->MemoryACPILevel.MinVoltage), &mvdd); 1386 PP_ASSERT_WITH_CODE((0 == result), 1387 "Cannot find ACPI VDDCI voltage value in Clock Dependency Table", 1388 ); 1389 } else { 1390 table->MemoryACPILevel.MclkFrequency = 1391 data->vbios_boot_state.mclk_bootup_value; 1392 table->MemoryACPILevel.MinVoltage = 1393 data->vbios_boot_state.vddci_bootup_value * VOLTAGE_SCALE; 1394 } 1395 1396 us_mvdd = 0; 1397 if ((SMU7_VOLTAGE_CONTROL_NONE == data->mvdd_control) || 1398 (data->mclk_dpm_key_disabled)) 1399 us_mvdd = data->vbios_boot_state.mvdd_bootup_value; 1400 else { 1401 if (!fiji_populate_mvdd_value(hwmgr, 1402 data->dpm_table.mclk_table.dpm_levels[0].value, 1403 &vol_level)) 1404 us_mvdd = vol_level.Voltage; 1405 } 1406 1407 table->MemoryACPILevel.MinMvdd = 1408 PP_HOST_TO_SMC_UL(us_mvdd * VOLTAGE_SCALE); 1409 1410 table->MemoryACPILevel.EnabledForThrottle = 0; 1411 table->MemoryACPILevel.EnabledForActivity = 0; 1412 table->MemoryACPILevel.UpHyst = 0; 1413 table->MemoryACPILevel.DownHyst = 100; 1414 table->MemoryACPILevel.VoltageDownHyst = 0; 1415 table->MemoryACPILevel.ActivityLevel = 1416 PP_HOST_TO_SMC_US(data->current_profile_setting.mclk_activity); 1417 1418 table->MemoryACPILevel.StutterEnable = false; 1419 CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MclkFrequency); 1420 CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MinVoltage); 1421 1422 return result; 1423 } 1424 1425 static int fiji_populate_smc_vce_level(struct pp_hwmgr *hwmgr, 1426 SMU73_Discrete_DpmTable *table) 1427 { 1428 int result = -EINVAL; 1429 uint8_t count; 1430 struct pp_atomctrl_clock_dividers_vi dividers; 1431 struct phm_ppt_v1_information *table_info = 1432 (struct phm_ppt_v1_information *)(hwmgr->pptable); 1433 struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = 1434 table_info->mm_dep_table; 1435 1436 table->VceLevelCount = (uint8_t)(mm_table->count); 1437 table->VceBootLevel = 0; 1438 1439 for (count = 0; count < table->VceLevelCount; count++) { 1440 table->VceLevel[count].Frequency = mm_table->entries[count].eclk; 1441 table->VceLevel[count].MinVoltage = 0; 1442 table->VceLevel[count].MinVoltage |= 1443 (mm_table->entries[count].vddc * VOLTAGE_SCALE) << VDDC_SHIFT; 1444 table->VceLevel[count].MinVoltage |= 1445 ((mm_table->entries[count].vddc - VDDC_VDDCI_DELTA) * 1446 VOLTAGE_SCALE) << VDDCI_SHIFT; 1447 table->VceLevel[count].MinVoltage |= 1 << PHASES_SHIFT; 1448 1449 /*retrieve divider value for VBIOS */ 1450 result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, 1451 table->VceLevel[count].Frequency, ÷rs); 1452 PP_ASSERT_WITH_CODE((0 == result), 1453 "can not find divide id for VCE engine clock", 1454 return result); 1455 1456 table->VceLevel[count].Divider = (uint8_t)dividers.pll_post_divider; 1457 1458 CONVERT_FROM_HOST_TO_SMC_UL(table->VceLevel[count].Frequency); 1459 CONVERT_FROM_HOST_TO_SMC_UL(table->VceLevel[count].MinVoltage); 1460 } 1461 return result; 1462 } 1463 1464 static int fiji_populate_smc_acp_level(struct pp_hwmgr *hwmgr, 1465 SMU73_Discrete_DpmTable *table) 1466 { 1467 int result = -EINVAL; 1468 uint8_t count; 1469 struct pp_atomctrl_clock_dividers_vi dividers; 1470 struct phm_ppt_v1_information *table_info = 1471 (struct phm_ppt_v1_information *)(hwmgr->pptable); 1472 struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = 1473 table_info->mm_dep_table; 1474 1475 table->AcpLevelCount = (uint8_t)(mm_table->count); 1476 table->AcpBootLevel = 0; 1477 1478 for (count = 0; count < table->AcpLevelCount; count++) { 1479 table->AcpLevel[count].Frequency = mm_table->entries[count].aclk; 1480 table->AcpLevel[count].MinVoltage |= (mm_table->entries[count].vddc * 1481 VOLTAGE_SCALE) << VDDC_SHIFT; 1482 table->AcpLevel[count].MinVoltage |= ((mm_table->entries[count].vddc - 1483 VDDC_VDDCI_DELTA) * VOLTAGE_SCALE) << VDDCI_SHIFT; 1484 table->AcpLevel[count].MinVoltage |= 1 << PHASES_SHIFT; 1485 1486 /* retrieve divider value for VBIOS */ 1487 result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, 1488 table->AcpLevel[count].Frequency, ÷rs); 1489 PP_ASSERT_WITH_CODE((0 == result), 1490 "can not find divide id for engine clock", return result); 1491 1492 table->AcpLevel[count].Divider = (uint8_t)dividers.pll_post_divider; 1493 1494 CONVERT_FROM_HOST_TO_SMC_UL(table->AcpLevel[count].Frequency); 1495 CONVERT_FROM_HOST_TO_SMC_UL(table->AcpLevel[count].MinVoltage); 1496 } 1497 return result; 1498 } 1499 1500 static int fiji_populate_memory_timing_parameters(struct pp_hwmgr *hwmgr, 1501 int32_t eng_clock, int32_t mem_clock, 1502 struct SMU73_Discrete_MCArbDramTimingTableEntry *arb_regs) 1503 { 1504 uint32_t dram_timing; 1505 uint32_t dram_timing2; 1506 uint32_t burstTime; 1507 ULONG trrds, trrdl; 1508 int result; 1509 1510 result = atomctrl_set_engine_dram_timings_rv770(hwmgr, 1511 eng_clock, mem_clock); 1512 PP_ASSERT_WITH_CODE(result == 0, 1513 "Error calling VBIOS to set DRAM_TIMING.", return result); 1514 1515 dram_timing = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING); 1516 dram_timing2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2); 1517 burstTime = cgs_read_register(hwmgr->device, mmMC_ARB_BURST_TIME); 1518 1519 trrds = PHM_GET_FIELD(burstTime, MC_ARB_BURST_TIME, TRRDS0); 1520 trrdl = PHM_GET_FIELD(burstTime, MC_ARB_BURST_TIME, TRRDL0); 1521 1522 arb_regs->McArbDramTiming = PP_HOST_TO_SMC_UL(dram_timing); 1523 arb_regs->McArbDramTiming2 = PP_HOST_TO_SMC_UL(dram_timing2); 1524 arb_regs->McArbBurstTime = (uint8_t)burstTime; 1525 arb_regs->TRRDS = (uint8_t)trrds; 1526 arb_regs->TRRDL = (uint8_t)trrdl; 1527 1528 return 0; 1529 } 1530 1531 static int fiji_program_memory_timing_parameters(struct pp_hwmgr *hwmgr) 1532 { 1533 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 1534 struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); 1535 struct SMU73_Discrete_MCArbDramTimingTable arb_regs; 1536 uint32_t i, j; 1537 int result = 0; 1538 1539 for (i = 0; i < data->dpm_table.sclk_table.count; i++) { 1540 for (j = 0; j < data->dpm_table.mclk_table.count; j++) { 1541 result = fiji_populate_memory_timing_parameters(hwmgr, 1542 data->dpm_table.sclk_table.dpm_levels[i].value, 1543 data->dpm_table.mclk_table.dpm_levels[j].value, 1544 &arb_regs.entries[i][j]); 1545 if (result) 1546 break; 1547 } 1548 } 1549 1550 if (!result) 1551 result = smu7_copy_bytes_to_smc( 1552 hwmgr, 1553 smu_data->smu7_data.arb_table_start, 1554 (uint8_t *)&arb_regs, 1555 sizeof(SMU73_Discrete_MCArbDramTimingTable), 1556 SMC_RAM_END); 1557 return result; 1558 } 1559 1560 static int fiji_populate_smc_uvd_level(struct pp_hwmgr *hwmgr, 1561 struct SMU73_Discrete_DpmTable *table) 1562 { 1563 int result = -EINVAL; 1564 uint8_t count; 1565 struct pp_atomctrl_clock_dividers_vi dividers; 1566 struct phm_ppt_v1_information *table_info = 1567 (struct phm_ppt_v1_information *)(hwmgr->pptable); 1568 struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = 1569 table_info->mm_dep_table; 1570 1571 table->UvdLevelCount = (uint8_t)(mm_table->count); 1572 table->UvdBootLevel = 0; 1573 1574 for (count = 0; count < table->UvdLevelCount; count++) { 1575 table->UvdLevel[count].MinVoltage = 0; 1576 table->UvdLevel[count].VclkFrequency = mm_table->entries[count].vclk; 1577 table->UvdLevel[count].DclkFrequency = mm_table->entries[count].dclk; 1578 table->UvdLevel[count].MinVoltage |= (mm_table->entries[count].vddc * 1579 VOLTAGE_SCALE) << VDDC_SHIFT; 1580 table->UvdLevel[count].MinVoltage |= ((mm_table->entries[count].vddc - 1581 VDDC_VDDCI_DELTA) * VOLTAGE_SCALE) << VDDCI_SHIFT; 1582 table->UvdLevel[count].MinVoltage |= 1 << PHASES_SHIFT; 1583 1584 /* retrieve divider value for VBIOS */ 1585 result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, 1586 table->UvdLevel[count].VclkFrequency, ÷rs); 1587 PP_ASSERT_WITH_CODE((0 == result), 1588 "can not find divide id for Vclk clock", return result); 1589 1590 table->UvdLevel[count].VclkDivider = (uint8_t)dividers.pll_post_divider; 1591 1592 result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, 1593 table->UvdLevel[count].DclkFrequency, ÷rs); 1594 PP_ASSERT_WITH_CODE((0 == result), 1595 "can not find divide id for Dclk clock", return result); 1596 1597 table->UvdLevel[count].DclkDivider = (uint8_t)dividers.pll_post_divider; 1598 1599 CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].VclkFrequency); 1600 CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].DclkFrequency); 1601 CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].MinVoltage); 1602 1603 } 1604 return result; 1605 } 1606 1607 static int fiji_populate_smc_boot_level(struct pp_hwmgr *hwmgr, 1608 struct SMU73_Discrete_DpmTable *table) 1609 { 1610 int result __unused = 0; 1611 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 1612 1613 table->GraphicsBootLevel = 0; 1614 table->MemoryBootLevel = 0; 1615 1616 /* find boot level from dpm table */ 1617 result = phm_find_boot_level(&(data->dpm_table.sclk_table), 1618 data->vbios_boot_state.sclk_bootup_value, 1619 (uint32_t *)&(table->GraphicsBootLevel)); 1620 1621 result = phm_find_boot_level(&(data->dpm_table.mclk_table), 1622 data->vbios_boot_state.mclk_bootup_value, 1623 (uint32_t *)&(table->MemoryBootLevel)); 1624 1625 table->BootVddc = data->vbios_boot_state.vddc_bootup_value * 1626 VOLTAGE_SCALE; 1627 table->BootVddci = data->vbios_boot_state.vddci_bootup_value * 1628 VOLTAGE_SCALE; 1629 table->BootMVdd = data->vbios_boot_state.mvdd_bootup_value * 1630 VOLTAGE_SCALE; 1631 1632 CONVERT_FROM_HOST_TO_SMC_US(table->BootVddc); 1633 CONVERT_FROM_HOST_TO_SMC_US(table->BootVddci); 1634 CONVERT_FROM_HOST_TO_SMC_US(table->BootMVdd); 1635 1636 return 0; 1637 } 1638 1639 static int fiji_populate_smc_initailial_state(struct pp_hwmgr *hwmgr) 1640 { 1641 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 1642 struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); 1643 struct phm_ppt_v1_information *table_info = 1644 (struct phm_ppt_v1_information *)(hwmgr->pptable); 1645 uint8_t count, level; 1646 1647 count = (uint8_t)(table_info->vdd_dep_on_sclk->count); 1648 for (level = 0; level < count; level++) { 1649 if (table_info->vdd_dep_on_sclk->entries[level].clk >= 1650 data->vbios_boot_state.sclk_bootup_value) { 1651 smu_data->smc_state_table.GraphicsBootLevel = level; 1652 break; 1653 } 1654 } 1655 1656 count = (uint8_t)(table_info->vdd_dep_on_mclk->count); 1657 for (level = 0; level < count; level++) { 1658 if (table_info->vdd_dep_on_mclk->entries[level].clk >= 1659 data->vbios_boot_state.mclk_bootup_value) { 1660 smu_data->smc_state_table.MemoryBootLevel = level; 1661 break; 1662 } 1663 } 1664 1665 return 0; 1666 } 1667 1668 static int fiji_populate_clock_stretcher_data_table(struct pp_hwmgr *hwmgr) 1669 { 1670 uint32_t ro, efuse, efuse2, clock_freq, volt_without_cks, 1671 volt_with_cks, value; 1672 uint16_t clock_freq_u16; 1673 struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); 1674 uint8_t type, i, j, cks_setting, stretch_amount, stretch_amount2, 1675 volt_offset = 0; 1676 struct phm_ppt_v1_information *table_info = 1677 (struct phm_ppt_v1_information *)(hwmgr->pptable); 1678 struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table = 1679 table_info->vdd_dep_on_sclk; 1680 1681 stretch_amount = (uint8_t)table_info->cac_dtp_table->usClockStretchAmount; 1682 1683 /* Read SMU_Eefuse to read and calculate RO and determine 1684 * if the part is SS or FF. if RO >= 1660MHz, part is FF. 1685 */ 1686 efuse = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, 1687 ixSMU_EFUSE_0 + (146 * 4)); 1688 efuse2 = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, 1689 ixSMU_EFUSE_0 + (148 * 4)); 1690 efuse &= 0xFF000000; 1691 efuse = efuse >> 24; 1692 efuse2 &= 0xF; 1693 1694 if (efuse2 == 1) 1695 ro = (2300 - 1350) * efuse / 255 + 1350; 1696 else 1697 ro = (2500 - 1000) * efuse / 255 + 1000; 1698 1699 if (ro >= 1660) 1700 type = 0; 1701 else 1702 type = 1; 1703 1704 /* Populate Stretch amount */ 1705 smu_data->smc_state_table.ClockStretcherAmount = stretch_amount; 1706 1707 /* Populate Sclk_CKS_masterEn0_7 and Sclk_voltageOffset */ 1708 for (i = 0; i < sclk_table->count; i++) { 1709 smu_data->smc_state_table.Sclk_CKS_masterEn0_7 |= 1710 sclk_table->entries[i].cks_enable << i; 1711 volt_without_cks = (uint32_t)((14041 * 1712 (sclk_table->entries[i].clk/100) / 10000 + 3571 + 75 - ro) * 1000 / 1713 (4026 - (13924 * (sclk_table->entries[i].clk/100) / 10000))); 1714 volt_with_cks = (uint32_t)((13946 * 1715 (sclk_table->entries[i].clk/100) / 10000 + 3320 + 45 - ro) * 1000 / 1716 (3664 - (11454 * (sclk_table->entries[i].clk/100) / 10000))); 1717 if (volt_without_cks >= volt_with_cks) 1718 volt_offset = (uint8_t)(((volt_without_cks - volt_with_cks + 1719 sclk_table->entries[i].cks_voffset) * 100 / 625) + 1); 1720 smu_data->smc_state_table.Sclk_voltageOffset[i] = volt_offset; 1721 } 1722 1723 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE, 1724 STRETCH_ENABLE, 0x0); 1725 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE, 1726 masterReset, 0x1); 1727 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE, 1728 staticEnable, 0x1); 1729 PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE, 1730 masterReset, 0x0); 1731 1732 /* Populate CKS Lookup Table */ 1733 if (stretch_amount == 1 || stretch_amount == 2 || stretch_amount == 5) 1734 stretch_amount2 = 0; 1735 else if (stretch_amount == 3 || stretch_amount == 4) 1736 stretch_amount2 = 1; 1737 else { 1738 phm_cap_unset(hwmgr->platform_descriptor.platformCaps, 1739 PHM_PlatformCaps_ClockStretcher); 1740 PP_ASSERT_WITH_CODE(false, 1741 "Stretch Amount in PPTable not supported", 1742 return -EINVAL); 1743 } 1744 1745 value = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, 1746 ixPWR_CKS_CNTL); 1747 value &= 0xFFC2FF87; 1748 smu_data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].minFreq = 1749 fiji_clock_stretcher_lookup_table[stretch_amount2][0]; 1750 smu_data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].maxFreq = 1751 fiji_clock_stretcher_lookup_table[stretch_amount2][1]; 1752 clock_freq_u16 = (uint16_t)(PP_SMC_TO_HOST_UL(smu_data->smc_state_table. 1753 GraphicsLevel[smu_data->smc_state_table.GraphicsDpmLevelCount - 1]. 1754 SclkFrequency) / 100); 1755 if (fiji_clock_stretcher_lookup_table[stretch_amount2][0] < 1756 clock_freq_u16 && 1757 fiji_clock_stretcher_lookup_table[stretch_amount2][1] > 1758 clock_freq_u16) { 1759 /* Program PWR_CKS_CNTL. CKS_USE_FOR_LOW_FREQ */ 1760 value |= (fiji_clock_stretcher_lookup_table[stretch_amount2][3]) << 16; 1761 /* Program PWR_CKS_CNTL. CKS_LDO_REFSEL */ 1762 value |= (fiji_clock_stretcher_lookup_table[stretch_amount2][2]) << 18; 1763 /* Program PWR_CKS_CNTL. CKS_STRETCH_AMOUNT */ 1764 value |= (fiji_clock_stretch_amount_conversion 1765 [fiji_clock_stretcher_lookup_table[stretch_amount2][3]] 1766 [stretch_amount]) << 3; 1767 } 1768 CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table.CKS_LOOKUPTable. 1769 CKS_LOOKUPTableEntry[0].minFreq); 1770 CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table.CKS_LOOKUPTable. 1771 CKS_LOOKUPTableEntry[0].maxFreq); 1772 smu_data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].setting = 1773 fiji_clock_stretcher_lookup_table[stretch_amount2][2] & 0x7F; 1774 smu_data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].setting |= 1775 (fiji_clock_stretcher_lookup_table[stretch_amount2][3]) << 7; 1776 1777 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 1778 ixPWR_CKS_CNTL, value); 1779 1780 /* Populate DDT Lookup Table */ 1781 for (i = 0; i < 4; i++) { 1782 /* Assign the minimum and maximum VID stored 1783 * in the last row of Clock Stretcher Voltage Table. 1784 */ 1785 smu_data->smc_state_table.ClockStretcherDataTable. 1786 ClockStretcherDataTableEntry[i].minVID = 1787 (uint8_t) fiji_clock_stretcher_ddt_table[type][i][2]; 1788 smu_data->smc_state_table.ClockStretcherDataTable. 1789 ClockStretcherDataTableEntry[i].maxVID = 1790 (uint8_t) fiji_clock_stretcher_ddt_table[type][i][3]; 1791 /* Loop through each SCLK and check the frequency 1792 * to see if it lies within the frequency for clock stretcher. 1793 */ 1794 for (j = 0; j < smu_data->smc_state_table.GraphicsDpmLevelCount; j++) { 1795 cks_setting = 0; 1796 clock_freq = PP_SMC_TO_HOST_UL( 1797 smu_data->smc_state_table.GraphicsLevel[j].SclkFrequency); 1798 /* Check the allowed frequency against the sclk level[j]. 1799 * Sclk's endianness has already been converted, 1800 * and it's in 10Khz unit, 1801 * as opposed to Data table, which is in Mhz unit. 1802 */ 1803 if (clock_freq >= 1804 (fiji_clock_stretcher_ddt_table[type][i][0]) * 100) { 1805 cks_setting |= 0x2; 1806 if (clock_freq < 1807 (fiji_clock_stretcher_ddt_table[type][i][1]) * 100) 1808 cks_setting |= 0x1; 1809 } 1810 smu_data->smc_state_table.ClockStretcherDataTable. 1811 ClockStretcherDataTableEntry[i].setting |= cks_setting << (j * 2); 1812 } 1813 CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table. 1814 ClockStretcherDataTable. 1815 ClockStretcherDataTableEntry[i].setting); 1816 } 1817 1818 value = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixPWR_CKS_CNTL); 1819 value &= 0xFFFFFFFE; 1820 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixPWR_CKS_CNTL, value); 1821 1822 return 0; 1823 } 1824 1825 static int fiji_populate_vr_config(struct pp_hwmgr *hwmgr, 1826 struct SMU73_Discrete_DpmTable *table) 1827 { 1828 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 1829 uint16_t config; 1830 1831 config = VR_MERGED_WITH_VDDC; 1832 table->VRConfig |= (config << VRCONF_VDDGFX_SHIFT); 1833 1834 /* Set Vddc Voltage Controller */ 1835 if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) { 1836 config = VR_SVI2_PLANE_1; 1837 table->VRConfig |= config; 1838 } else { 1839 PP_ASSERT_WITH_CODE(false, 1840 "VDDC should be on SVI2 control in merged mode!", 1841 ); 1842 } 1843 /* Set Vddci Voltage Controller */ 1844 if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) { 1845 config = VR_SVI2_PLANE_2; /* only in merged mode */ 1846 table->VRConfig |= (config << VRCONF_VDDCI_SHIFT); 1847 } else if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) { 1848 config = VR_SMIO_PATTERN_1; 1849 table->VRConfig |= (config << VRCONF_VDDCI_SHIFT); 1850 } else { 1851 config = VR_STATIC_VOLTAGE; 1852 table->VRConfig |= (config << VRCONF_VDDCI_SHIFT); 1853 } 1854 /* Set Mvdd Voltage Controller */ 1855 if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->mvdd_control) { 1856 config = VR_SVI2_PLANE_2; 1857 table->VRConfig |= (config << VRCONF_MVDD_SHIFT); 1858 } else if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) { 1859 config = VR_SMIO_PATTERN_2; 1860 table->VRConfig |= (config << VRCONF_MVDD_SHIFT); 1861 } else { 1862 config = VR_STATIC_VOLTAGE; 1863 table->VRConfig |= (config << VRCONF_MVDD_SHIFT); 1864 } 1865 1866 return 0; 1867 } 1868 1869 static int fiji_init_arb_table_index(struct pp_hwmgr *hwmgr) 1870 { 1871 struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); 1872 uint32_t tmp; 1873 int result; 1874 1875 /* This is a read-modify-write on the first byte of the ARB table. 1876 * The first byte in the SMU73_Discrete_MCArbDramTimingTable structure 1877 * is the field 'current'. 1878 * This solution is ugly, but we never write the whole table only 1879 * individual fields in it. 1880 * In reality this field should not be in that structure 1881 * but in a soft register. 1882 */ 1883 result = smu7_read_smc_sram_dword(hwmgr, 1884 smu_data->smu7_data.arb_table_start, &tmp, SMC_RAM_END); 1885 1886 if (result) 1887 return result; 1888 1889 tmp &= 0x00FFFFFF; 1890 tmp |= ((uint32_t)MC_CG_ARB_FREQ_F1) << 24; 1891 1892 return smu7_write_smc_sram_dword(hwmgr, 1893 smu_data->smu7_data.arb_table_start, tmp, SMC_RAM_END); 1894 } 1895 1896 static int fiji_setup_dpm_led_config(struct pp_hwmgr *hwmgr) 1897 { 1898 pp_atomctrl_voltage_table param_led_dpm; 1899 int result = 0; 1900 u32 mask = 0; 1901 1902 result = atomctrl_get_voltage_table_v3(hwmgr, 1903 VOLTAGE_TYPE_LEDDPM, VOLTAGE_OBJ_GPIO_LUT, 1904 ¶m_led_dpm); 1905 if (result == 0) { 1906 int i, j; 1907 u32 tmp = param_led_dpm.mask_low; 1908 1909 for (i = 0, j = 0; i < 32; i++) { 1910 if (tmp & 1) { 1911 mask |= (i << (8 * j)); 1912 if (++j >= 3) 1913 break; 1914 } 1915 tmp >>= 1; 1916 } 1917 } 1918 if (mask) 1919 smum_send_msg_to_smc_with_parameter(hwmgr, 1920 PPSMC_MSG_LedConfig, 1921 mask); 1922 return 0; 1923 } 1924 1925 static int fiji_init_smc_table(struct pp_hwmgr *hwmgr) 1926 { 1927 int result; 1928 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 1929 struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); 1930 struct phm_ppt_v1_information *table_info = 1931 (struct phm_ppt_v1_information *)(hwmgr->pptable); 1932 struct SMU73_Discrete_DpmTable *table = &(smu_data->smc_state_table); 1933 uint8_t i; 1934 struct pp_atomctrl_gpio_pin_assignment gpio_pin; 1935 1936 fiji_initialize_power_tune_defaults(hwmgr); 1937 1938 if (SMU7_VOLTAGE_CONTROL_NONE != data->voltage_control) 1939 fiji_populate_smc_voltage_tables(hwmgr, table); 1940 1941 table->SystemFlags = 0; 1942 1943 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, 1944 PHM_PlatformCaps_AutomaticDCTransition)) 1945 table->SystemFlags |= PPSMC_SYSTEMFLAG_GPIO_DC; 1946 1947 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, 1948 PHM_PlatformCaps_StepVddc)) 1949 table->SystemFlags |= PPSMC_SYSTEMFLAG_STEPVDDC; 1950 1951 if (data->is_memory_gddr5) 1952 table->SystemFlags |= PPSMC_SYSTEMFLAG_GDDR5; 1953 1954 if (data->ulv_supported && table_info->us_ulv_voltage_offset) { 1955 result = fiji_populate_ulv_state(hwmgr, table); 1956 PP_ASSERT_WITH_CODE(0 == result, 1957 "Failed to initialize ULV state!", return result); 1958 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 1959 ixCG_ULV_PARAMETER, 0x40035); 1960 } 1961 1962 result = fiji_populate_smc_link_level(hwmgr, table); 1963 PP_ASSERT_WITH_CODE(0 == result, 1964 "Failed to initialize Link Level!", return result); 1965 1966 result = fiji_populate_all_graphic_levels(hwmgr); 1967 PP_ASSERT_WITH_CODE(0 == result, 1968 "Failed to initialize Graphics Level!", return result); 1969 1970 result = fiji_populate_all_memory_levels(hwmgr); 1971 PP_ASSERT_WITH_CODE(0 == result, 1972 "Failed to initialize Memory Level!", return result); 1973 1974 result = fiji_populate_smc_acpi_level(hwmgr, table); 1975 PP_ASSERT_WITH_CODE(0 == result, 1976 "Failed to initialize ACPI Level!", return result); 1977 1978 result = fiji_populate_smc_vce_level(hwmgr, table); 1979 PP_ASSERT_WITH_CODE(0 == result, 1980 "Failed to initialize VCE Level!", return result); 1981 1982 result = fiji_populate_smc_acp_level(hwmgr, table); 1983 PP_ASSERT_WITH_CODE(0 == result, 1984 "Failed to initialize ACP Level!", return result); 1985 1986 /* Since only the initial state is completely set up at this point 1987 * (the other states are just copies of the boot state) we only 1988 * need to populate the ARB settings for the initial state. 1989 */ 1990 result = fiji_program_memory_timing_parameters(hwmgr); 1991 PP_ASSERT_WITH_CODE(0 == result, 1992 "Failed to Write ARB settings for the initial state.", return result); 1993 1994 result = fiji_populate_smc_uvd_level(hwmgr, table); 1995 PP_ASSERT_WITH_CODE(0 == result, 1996 "Failed to initialize UVD Level!", return result); 1997 1998 result = fiji_populate_smc_boot_level(hwmgr, table); 1999 PP_ASSERT_WITH_CODE(0 == result, 2000 "Failed to initialize Boot Level!", return result); 2001 2002 result = fiji_populate_smc_initailial_state(hwmgr); 2003 PP_ASSERT_WITH_CODE(0 == result, 2004 "Failed to initialize Boot State!", return result); 2005 2006 result = fiji_populate_bapm_parameters_in_dpm_table(hwmgr); 2007 PP_ASSERT_WITH_CODE(0 == result, 2008 "Failed to populate BAPM Parameters!", return result); 2009 2010 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, 2011 PHM_PlatformCaps_ClockStretcher)) { 2012 result = fiji_populate_clock_stretcher_data_table(hwmgr); 2013 PP_ASSERT_WITH_CODE(0 == result, 2014 "Failed to populate Clock Stretcher Data Table!", 2015 return result); 2016 } 2017 2018 table->GraphicsVoltageChangeEnable = 1; 2019 table->GraphicsThermThrottleEnable = 1; 2020 table->GraphicsInterval = 1; 2021 table->VoltageInterval = 1; 2022 table->ThermalInterval = 1; 2023 table->TemperatureLimitHigh = 2024 table_info->cac_dtp_table->usTargetOperatingTemp * 2025 SMU7_Q88_FORMAT_CONVERSION_UNIT; 2026 table->TemperatureLimitLow = 2027 (table_info->cac_dtp_table->usTargetOperatingTemp - 1) * 2028 SMU7_Q88_FORMAT_CONVERSION_UNIT; 2029 table->MemoryVoltageChangeEnable = 1; 2030 table->MemoryInterval = 1; 2031 table->VoltageResponseTime = 0; 2032 table->PhaseResponseTime = 0; 2033 table->MemoryThermThrottleEnable = 1; 2034 table->PCIeBootLinkLevel = 0; /* 0:Gen1 1:Gen2 2:Gen3*/ 2035 table->PCIeGenInterval = 1; 2036 table->VRConfig = 0; 2037 2038 result = fiji_populate_vr_config(hwmgr, table); 2039 PP_ASSERT_WITH_CODE(0 == result, 2040 "Failed to populate VRConfig setting!", return result); 2041 data->vr_config = table->VRConfig; 2042 table->ThermGpio = 17; 2043 table->SclkStepSize = 0x4000; 2044 2045 if (atomctrl_get_pp_assign_pin(hwmgr, VDDC_VRHOT_GPIO_PINID, &gpio_pin)) { 2046 table->VRHotGpio = gpio_pin.uc_gpio_pin_bit_shift; 2047 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 2048 PHM_PlatformCaps_RegulatorHot); 2049 } else { 2050 table->VRHotGpio = SMU7_UNUSED_GPIO_PIN; 2051 phm_cap_unset(hwmgr->platform_descriptor.platformCaps, 2052 PHM_PlatformCaps_RegulatorHot); 2053 } 2054 2055 if (atomctrl_get_pp_assign_pin(hwmgr, PP_AC_DC_SWITCH_GPIO_PINID, 2056 &gpio_pin)) { 2057 table->AcDcGpio = gpio_pin.uc_gpio_pin_bit_shift; 2058 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 2059 PHM_PlatformCaps_AutomaticDCTransition); 2060 } else { 2061 table->AcDcGpio = SMU7_UNUSED_GPIO_PIN; 2062 phm_cap_unset(hwmgr->platform_descriptor.platformCaps, 2063 PHM_PlatformCaps_AutomaticDCTransition); 2064 } 2065 2066 /* Thermal Output GPIO */ 2067 if (atomctrl_get_pp_assign_pin(hwmgr, THERMAL_INT_OUTPUT_GPIO_PINID, 2068 &gpio_pin)) { 2069 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 2070 PHM_PlatformCaps_ThermalOutGPIO); 2071 2072 table->ThermOutGpio = gpio_pin.uc_gpio_pin_bit_shift; 2073 2074 /* For porlarity read GPIOPAD_A with assigned Gpio pin 2075 * since VBIOS will program this register to set 'inactive state', 2076 * driver can then determine 'active state' from this and 2077 * program SMU with correct polarity 2078 */ 2079 table->ThermOutPolarity = (0 == (cgs_read_register(hwmgr->device, mmGPIOPAD_A) & 2080 (1 << gpio_pin.uc_gpio_pin_bit_shift))) ? 1:0; 2081 table->ThermOutMode = SMU7_THERM_OUT_MODE_THERM_ONLY; 2082 2083 /* if required, combine VRHot/PCC with thermal out GPIO */ 2084 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, 2085 PHM_PlatformCaps_RegulatorHot) && 2086 phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, 2087 PHM_PlatformCaps_CombinePCCWithThermalSignal)) 2088 table->ThermOutMode = SMU7_THERM_OUT_MODE_THERM_VRHOT; 2089 } else { 2090 phm_cap_unset(hwmgr->platform_descriptor.platformCaps, 2091 PHM_PlatformCaps_ThermalOutGPIO); 2092 table->ThermOutGpio = 17; 2093 table->ThermOutPolarity = 1; 2094 table->ThermOutMode = SMU7_THERM_OUT_MODE_DISABLE; 2095 } 2096 2097 for (i = 0; i < SMU73_MAX_ENTRIES_SMIO; i++) 2098 table->Smio[i] = PP_HOST_TO_SMC_UL(table->Smio[i]); 2099 2100 CONVERT_FROM_HOST_TO_SMC_UL(table->SystemFlags); 2101 CONVERT_FROM_HOST_TO_SMC_UL(table->VRConfig); 2102 CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMask1); 2103 CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMask2); 2104 CONVERT_FROM_HOST_TO_SMC_UL(table->SclkStepSize); 2105 CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitHigh); 2106 CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitLow); 2107 CONVERT_FROM_HOST_TO_SMC_US(table->VoltageResponseTime); 2108 CONVERT_FROM_HOST_TO_SMC_US(table->PhaseResponseTime); 2109 2110 /* Upload all dpm data to SMC memory.(dpm level, dpm level count etc) */ 2111 result = smu7_copy_bytes_to_smc(hwmgr, 2112 smu_data->smu7_data.dpm_table_start + 2113 offsetof(SMU73_Discrete_DpmTable, SystemFlags), 2114 (uint8_t *)&(table->SystemFlags), 2115 sizeof(SMU73_Discrete_DpmTable) - 3 * sizeof(SMU73_PIDController), 2116 SMC_RAM_END); 2117 PP_ASSERT_WITH_CODE(0 == result, 2118 "Failed to upload dpm data to SMC memory!", return result); 2119 2120 result = fiji_init_arb_table_index(hwmgr); 2121 PP_ASSERT_WITH_CODE(0 == result, 2122 "Failed to upload arb data to SMC memory!", return result); 2123 2124 result = fiji_populate_pm_fuses(hwmgr); 2125 PP_ASSERT_WITH_CODE(0 == result, 2126 "Failed to populate PM fuses to SMC memory!", return result); 2127 2128 result = fiji_setup_dpm_led_config(hwmgr); 2129 PP_ASSERT_WITH_CODE(0 == result, 2130 "Failed to setup dpm led config", return result); 2131 2132 return 0; 2133 } 2134 2135 static int fiji_thermal_setup_fan_table(struct pp_hwmgr *hwmgr) 2136 { 2137 struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); 2138 2139 SMU73_Discrete_FanTable fan_table = { FDO_MODE_HARDWARE }; 2140 uint32_t duty100; 2141 uint32_t t_diff1, t_diff2, pwm_diff1, pwm_diff2; 2142 uint16_t fdo_min, slope1, slope2; 2143 uint32_t reference_clock; 2144 int res; 2145 uint64_t tmp64; 2146 2147 if (hwmgr->thermal_controller.fanInfo.bNoFan) { 2148 phm_cap_unset(hwmgr->platform_descriptor.platformCaps, 2149 PHM_PlatformCaps_MicrocodeFanControl); 2150 return 0; 2151 } 2152 2153 if (smu_data->smu7_data.fan_table_start == 0) { 2154 phm_cap_unset(hwmgr->platform_descriptor.platformCaps, 2155 PHM_PlatformCaps_MicrocodeFanControl); 2156 return 0; 2157 } 2158 2159 duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, 2160 CG_FDO_CTRL1, FMAX_DUTY100); 2161 2162 if (duty100 == 0) { 2163 phm_cap_unset(hwmgr->platform_descriptor.platformCaps, 2164 PHM_PlatformCaps_MicrocodeFanControl); 2165 return 0; 2166 } 2167 2168 tmp64 = hwmgr->thermal_controller.advanceFanControlParameters. 2169 usPWMMin * duty100; 2170 do_div(tmp64, 10000); 2171 fdo_min = (uint16_t)tmp64; 2172 2173 t_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usTMed - 2174 hwmgr->thermal_controller.advanceFanControlParameters.usTMin; 2175 t_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usTHigh - 2176 hwmgr->thermal_controller.advanceFanControlParameters.usTMed; 2177 2178 pwm_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed - 2179 hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin; 2180 pwm_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh - 2181 hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed; 2182 2183 slope1 = (uint16_t)((50 + ((16 * duty100 * pwm_diff1) / t_diff1)) / 100); 2184 slope2 = (uint16_t)((50 + ((16 * duty100 * pwm_diff2) / t_diff2)) / 100); 2185 2186 fan_table.TempMin = cpu_to_be16((50 + hwmgr-> 2187 thermal_controller.advanceFanControlParameters.usTMin) / 100); 2188 fan_table.TempMed = cpu_to_be16((50 + hwmgr-> 2189 thermal_controller.advanceFanControlParameters.usTMed) / 100); 2190 fan_table.TempMax = cpu_to_be16((50 + hwmgr-> 2191 thermal_controller.advanceFanControlParameters.usTMax) / 100); 2192 2193 fan_table.Slope1 = cpu_to_be16(slope1); 2194 fan_table.Slope2 = cpu_to_be16(slope2); 2195 2196 fan_table.FdoMin = cpu_to_be16(fdo_min); 2197 2198 fan_table.HystDown = cpu_to_be16(hwmgr-> 2199 thermal_controller.advanceFanControlParameters.ucTHyst); 2200 2201 fan_table.HystUp = cpu_to_be16(1); 2202 2203 fan_table.HystSlope = cpu_to_be16(1); 2204 2205 fan_table.TempRespLim = cpu_to_be16(5); 2206 2207 reference_clock = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev); 2208 2209 fan_table.RefreshPeriod = cpu_to_be32((hwmgr-> 2210 thermal_controller.advanceFanControlParameters.ulCycleDelay * 2211 reference_clock) / 1600); 2212 2213 fan_table.FdoMax = cpu_to_be16((uint16_t)duty100); 2214 2215 fan_table.TempSrc = (uint8_t)PHM_READ_VFPF_INDIRECT_FIELD( 2216 hwmgr->device, CGS_IND_REG__SMC, 2217 CG_MULT_THERMAL_CTRL, TEMP_SEL); 2218 2219 res = smu7_copy_bytes_to_smc(hwmgr, smu_data->smu7_data.fan_table_start, 2220 (uint8_t *)&fan_table, (uint32_t)sizeof(fan_table), 2221 SMC_RAM_END); 2222 2223 if (!res && hwmgr->thermal_controller. 2224 advanceFanControlParameters.ucMinimumPWMLimit) 2225 res = smum_send_msg_to_smc_with_parameter(hwmgr, 2226 PPSMC_MSG_SetFanMinPwm, 2227 hwmgr->thermal_controller. 2228 advanceFanControlParameters.ucMinimumPWMLimit); 2229 2230 if (!res && hwmgr->thermal_controller. 2231 advanceFanControlParameters.ulMinFanSCLKAcousticLimit) 2232 res = smum_send_msg_to_smc_with_parameter(hwmgr, 2233 PPSMC_MSG_SetFanSclkTarget, 2234 hwmgr->thermal_controller. 2235 advanceFanControlParameters.ulMinFanSCLKAcousticLimit); 2236 2237 if (res) 2238 phm_cap_unset(hwmgr->platform_descriptor.platformCaps, 2239 PHM_PlatformCaps_MicrocodeFanControl); 2240 2241 return 0; 2242 } 2243 2244 2245 static int fiji_thermal_avfs_enable(struct pp_hwmgr *hwmgr) 2246 { 2247 if (!hwmgr->avfs_supported) 2248 return 0; 2249 2250 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_EnableAvfs); 2251 2252 return 0; 2253 } 2254 2255 static int fiji_program_mem_timing_parameters(struct pp_hwmgr *hwmgr) 2256 { 2257 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 2258 2259 if (data->need_update_smu7_dpm_table & 2260 (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_OD_UPDATE_MCLK)) 2261 return fiji_program_memory_timing_parameters(hwmgr); 2262 2263 return 0; 2264 } 2265 2266 static int fiji_update_sclk_threshold(struct pp_hwmgr *hwmgr) 2267 { 2268 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 2269 struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); 2270 2271 int result = 0; 2272 uint32_t low_sclk_interrupt_threshold = 0; 2273 2274 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, 2275 PHM_PlatformCaps_SclkThrottleLowNotification) 2276 && (data->low_sclk_interrupt_threshold != 0)) { 2277 low_sclk_interrupt_threshold = 2278 data->low_sclk_interrupt_threshold; 2279 2280 CONVERT_FROM_HOST_TO_SMC_UL(low_sclk_interrupt_threshold); 2281 2282 result = smu7_copy_bytes_to_smc( 2283 hwmgr, 2284 smu_data->smu7_data.dpm_table_start + 2285 offsetof(SMU73_Discrete_DpmTable, 2286 LowSclkInterruptThreshold), 2287 (uint8_t *)&low_sclk_interrupt_threshold, 2288 sizeof(uint32_t), 2289 SMC_RAM_END); 2290 } 2291 result = fiji_program_mem_timing_parameters(hwmgr); 2292 PP_ASSERT_WITH_CODE((result == 0), 2293 "Failed to program memory timing parameters!", 2294 ); 2295 return result; 2296 } 2297 2298 static uint32_t fiji_get_offsetof(uint32_t type, uint32_t member) 2299 { 2300 switch (type) { 2301 case SMU_SoftRegisters: 2302 switch (member) { 2303 case HandshakeDisables: 2304 return offsetof(SMU73_SoftRegisters, HandshakeDisables); 2305 case VoltageChangeTimeout: 2306 return offsetof(SMU73_SoftRegisters, VoltageChangeTimeout); 2307 case AverageGraphicsActivity: 2308 return offsetof(SMU73_SoftRegisters, AverageGraphicsActivity); 2309 case AverageMemoryActivity: 2310 return offsetof(SMU73_SoftRegisters, AverageMemoryActivity); 2311 case PreVBlankGap: 2312 return offsetof(SMU73_SoftRegisters, PreVBlankGap); 2313 case VBlankTimeout: 2314 return offsetof(SMU73_SoftRegisters, VBlankTimeout); 2315 case UcodeLoadStatus: 2316 return offsetof(SMU73_SoftRegisters, UcodeLoadStatus); 2317 case DRAM_LOG_ADDR_H: 2318 return offsetof(SMU73_SoftRegisters, DRAM_LOG_ADDR_H); 2319 case DRAM_LOG_ADDR_L: 2320 return offsetof(SMU73_SoftRegisters, DRAM_LOG_ADDR_L); 2321 case DRAM_LOG_PHY_ADDR_H: 2322 return offsetof(SMU73_SoftRegisters, DRAM_LOG_PHY_ADDR_H); 2323 case DRAM_LOG_PHY_ADDR_L: 2324 return offsetof(SMU73_SoftRegisters, DRAM_LOG_PHY_ADDR_L); 2325 case DRAM_LOG_BUFF_SIZE: 2326 return offsetof(SMU73_SoftRegisters, DRAM_LOG_BUFF_SIZE); 2327 } 2328 break; 2329 case SMU_Discrete_DpmTable: 2330 switch (member) { 2331 case UvdBootLevel: 2332 return offsetof(SMU73_Discrete_DpmTable, UvdBootLevel); 2333 case VceBootLevel: 2334 return offsetof(SMU73_Discrete_DpmTable, VceBootLevel); 2335 case LowSclkInterruptThreshold: 2336 return offsetof(SMU73_Discrete_DpmTable, LowSclkInterruptThreshold); 2337 } 2338 break; 2339 } 2340 pr_warn("can't get the offset of type %x member %x\n", type, member); 2341 return 0; 2342 } 2343 2344 static uint32_t fiji_get_mac_definition(uint32_t value) 2345 { 2346 switch (value) { 2347 case SMU_MAX_LEVELS_GRAPHICS: 2348 return SMU73_MAX_LEVELS_GRAPHICS; 2349 case SMU_MAX_LEVELS_MEMORY: 2350 return SMU73_MAX_LEVELS_MEMORY; 2351 case SMU_MAX_LEVELS_LINK: 2352 return SMU73_MAX_LEVELS_LINK; 2353 case SMU_MAX_ENTRIES_SMIO: 2354 return SMU73_MAX_ENTRIES_SMIO; 2355 case SMU_MAX_LEVELS_VDDC: 2356 return SMU73_MAX_LEVELS_VDDC; 2357 case SMU_MAX_LEVELS_VDDGFX: 2358 return SMU73_MAX_LEVELS_VDDGFX; 2359 case SMU_MAX_LEVELS_VDDCI: 2360 return SMU73_MAX_LEVELS_VDDCI; 2361 case SMU_MAX_LEVELS_MVDD: 2362 return SMU73_MAX_LEVELS_MVDD; 2363 } 2364 2365 pr_warn("can't get the mac of %x\n", value); 2366 return 0; 2367 } 2368 2369 2370 static int fiji_update_uvd_smc_table(struct pp_hwmgr *hwmgr) 2371 { 2372 struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); 2373 uint32_t mm_boot_level_offset, mm_boot_level_value; 2374 struct phm_ppt_v1_information *table_info = 2375 (struct phm_ppt_v1_information *)(hwmgr->pptable); 2376 2377 smu_data->smc_state_table.UvdBootLevel = 0; 2378 if (table_info->mm_dep_table->count > 0) 2379 smu_data->smc_state_table.UvdBootLevel = 2380 (uint8_t) (table_info->mm_dep_table->count - 1); 2381 mm_boot_level_offset = smu_data->smu7_data.dpm_table_start + offsetof(SMU73_Discrete_DpmTable, 2382 UvdBootLevel); 2383 mm_boot_level_offset /= 4; 2384 mm_boot_level_offset *= 4; 2385 mm_boot_level_value = cgs_read_ind_register(hwmgr->device, 2386 CGS_IND_REG__SMC, mm_boot_level_offset); 2387 mm_boot_level_value &= 0x00FFFFFF; 2388 mm_boot_level_value |= smu_data->smc_state_table.UvdBootLevel << 24; 2389 cgs_write_ind_register(hwmgr->device, 2390 CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value); 2391 2392 if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, 2393 PHM_PlatformCaps_UVDDPM) || 2394 phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, 2395 PHM_PlatformCaps_StablePState)) 2396 smum_send_msg_to_smc_with_parameter(hwmgr, 2397 PPSMC_MSG_UVDDPM_SetEnabledMask, 2398 (uint32_t)(1 << smu_data->smc_state_table.UvdBootLevel)); 2399 return 0; 2400 } 2401 2402 static int fiji_update_vce_smc_table(struct pp_hwmgr *hwmgr) 2403 { 2404 struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); 2405 uint32_t mm_boot_level_offset, mm_boot_level_value; 2406 struct phm_ppt_v1_information *table_info = 2407 (struct phm_ppt_v1_information *)(hwmgr->pptable); 2408 2409 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, 2410 PHM_PlatformCaps_StablePState)) 2411 smu_data->smc_state_table.VceBootLevel = 2412 (uint8_t) (table_info->mm_dep_table->count - 1); 2413 else 2414 smu_data->smc_state_table.VceBootLevel = 0; 2415 2416 mm_boot_level_offset = smu_data->smu7_data.dpm_table_start + 2417 offsetof(SMU73_Discrete_DpmTable, VceBootLevel); 2418 mm_boot_level_offset /= 4; 2419 mm_boot_level_offset *= 4; 2420 mm_boot_level_value = cgs_read_ind_register(hwmgr->device, 2421 CGS_IND_REG__SMC, mm_boot_level_offset); 2422 mm_boot_level_value &= 0xFF00FFFF; 2423 mm_boot_level_value |= smu_data->smc_state_table.VceBootLevel << 16; 2424 cgs_write_ind_register(hwmgr->device, 2425 CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value); 2426 2427 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_StablePState)) 2428 smum_send_msg_to_smc_with_parameter(hwmgr, 2429 PPSMC_MSG_VCEDPM_SetEnabledMask, 2430 (uint32_t)1 << smu_data->smc_state_table.VceBootLevel); 2431 return 0; 2432 } 2433 2434 static int fiji_update_smc_table(struct pp_hwmgr *hwmgr, uint32_t type) 2435 { 2436 switch (type) { 2437 case SMU_UVD_TABLE: 2438 fiji_update_uvd_smc_table(hwmgr); 2439 break; 2440 case SMU_VCE_TABLE: 2441 fiji_update_vce_smc_table(hwmgr); 2442 break; 2443 default: 2444 break; 2445 } 2446 return 0; 2447 } 2448 2449 static int fiji_process_firmware_header(struct pp_hwmgr *hwmgr) 2450 { 2451 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 2452 struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); 2453 uint32_t tmp; 2454 int result; 2455 bool error = false; 2456 2457 result = smu7_read_smc_sram_dword(hwmgr, 2458 SMU7_FIRMWARE_HEADER_LOCATION + 2459 offsetof(SMU73_Firmware_Header, DpmTable), 2460 &tmp, SMC_RAM_END); 2461 2462 if (0 == result) 2463 smu_data->smu7_data.dpm_table_start = tmp; 2464 2465 error |= (0 != result); 2466 2467 result = smu7_read_smc_sram_dword(hwmgr, 2468 SMU7_FIRMWARE_HEADER_LOCATION + 2469 offsetof(SMU73_Firmware_Header, SoftRegisters), 2470 &tmp, SMC_RAM_END); 2471 2472 if (!result) { 2473 data->soft_regs_start = tmp; 2474 smu_data->smu7_data.soft_regs_start = tmp; 2475 } 2476 2477 error |= (0 != result); 2478 2479 result = smu7_read_smc_sram_dword(hwmgr, 2480 SMU7_FIRMWARE_HEADER_LOCATION + 2481 offsetof(SMU73_Firmware_Header, mcRegisterTable), 2482 &tmp, SMC_RAM_END); 2483 2484 if (!result) 2485 smu_data->smu7_data.mc_reg_table_start = tmp; 2486 2487 result = smu7_read_smc_sram_dword(hwmgr, 2488 SMU7_FIRMWARE_HEADER_LOCATION + 2489 offsetof(SMU73_Firmware_Header, FanTable), 2490 &tmp, SMC_RAM_END); 2491 2492 if (!result) 2493 smu_data->smu7_data.fan_table_start = tmp; 2494 2495 error |= (0 != result); 2496 2497 result = smu7_read_smc_sram_dword(hwmgr, 2498 SMU7_FIRMWARE_HEADER_LOCATION + 2499 offsetof(SMU73_Firmware_Header, mcArbDramTimingTable), 2500 &tmp, SMC_RAM_END); 2501 2502 if (!result) 2503 smu_data->smu7_data.arb_table_start = tmp; 2504 2505 error |= (0 != result); 2506 2507 result = smu7_read_smc_sram_dword(hwmgr, 2508 SMU7_FIRMWARE_HEADER_LOCATION + 2509 offsetof(SMU73_Firmware_Header, Version), 2510 &tmp, SMC_RAM_END); 2511 2512 if (!result) 2513 hwmgr->microcode_version_info.SMC = tmp; 2514 2515 error |= (0 != result); 2516 2517 return error ? -1 : 0; 2518 } 2519 2520 static int fiji_initialize_mc_reg_table(struct pp_hwmgr *hwmgr) 2521 { 2522 2523 /* Program additional LP registers 2524 * that are no longer programmed by VBIOS 2525 */ 2526 cgs_write_register(hwmgr->device, mmMC_SEQ_RAS_TIMING_LP, 2527 cgs_read_register(hwmgr->device, mmMC_SEQ_RAS_TIMING)); 2528 cgs_write_register(hwmgr->device, mmMC_SEQ_CAS_TIMING_LP, 2529 cgs_read_register(hwmgr->device, mmMC_SEQ_CAS_TIMING)); 2530 cgs_write_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2_LP, 2531 cgs_read_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2)); 2532 cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1_LP, 2533 cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1)); 2534 cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0_LP, 2535 cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0)); 2536 cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1_LP, 2537 cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1)); 2538 cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_TIMING_LP, 2539 cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_TIMING)); 2540 2541 return 0; 2542 } 2543 2544 static bool fiji_is_dpm_running(struct pp_hwmgr *hwmgr) 2545 { 2546 return (1 == PHM_READ_INDIRECT_FIELD(hwmgr->device, 2547 CGS_IND_REG__SMC, FEATURE_STATUS, VOLTAGE_CONTROLLER_ON)) 2548 ? true : false; 2549 } 2550 2551 static int fiji_update_dpm_settings(struct pp_hwmgr *hwmgr, 2552 void *profile_setting) 2553 { 2554 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 2555 struct fiji_smumgr *smu_data = (struct fiji_smumgr *) 2556 (hwmgr->smu_backend); 2557 struct profile_mode_setting *setting; 2558 struct SMU73_Discrete_GraphicsLevel *levels = 2559 smu_data->smc_state_table.GraphicsLevel; 2560 uint32_t array = smu_data->smu7_data.dpm_table_start + 2561 offsetof(SMU73_Discrete_DpmTable, GraphicsLevel); 2562 2563 uint32_t mclk_array = smu_data->smu7_data.dpm_table_start + 2564 offsetof(SMU73_Discrete_DpmTable, MemoryLevel); 2565 struct SMU73_Discrete_MemoryLevel *mclk_levels = 2566 smu_data->smc_state_table.MemoryLevel; 2567 uint32_t i; 2568 uint32_t offset, up_hyst_offset, down_hyst_offset, clk_activity_offset, tmp; 2569 2570 if (profile_setting == NULL) 2571 return -EINVAL; 2572 2573 setting = (struct profile_mode_setting *)profile_setting; 2574 2575 if (setting->bupdate_sclk) { 2576 if (!data->sclk_dpm_key_disabled) 2577 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_SCLKDPM_FreezeLevel); 2578 for (i = 0; i < smu_data->smc_state_table.GraphicsDpmLevelCount; i++) { 2579 if (levels[i].ActivityLevel != 2580 cpu_to_be16(setting->sclk_activity)) { 2581 levels[i].ActivityLevel = cpu_to_be16(setting->sclk_activity); 2582 2583 clk_activity_offset = array + (sizeof(SMU73_Discrete_GraphicsLevel) * i) 2584 + offsetof(SMU73_Discrete_GraphicsLevel, ActivityLevel); 2585 offset = clk_activity_offset & ~0x3; 2586 tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset)); 2587 tmp = phm_set_field_to_u32(clk_activity_offset, tmp, levels[i].ActivityLevel, sizeof(uint16_t)); 2588 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp)); 2589 2590 } 2591 if (levels[i].UpHyst != setting->sclk_up_hyst || 2592 levels[i].DownHyst != setting->sclk_down_hyst) { 2593 levels[i].UpHyst = setting->sclk_up_hyst; 2594 levels[i].DownHyst = setting->sclk_down_hyst; 2595 up_hyst_offset = array + (sizeof(SMU73_Discrete_GraphicsLevel) * i) 2596 + offsetof(SMU73_Discrete_GraphicsLevel, UpHyst); 2597 down_hyst_offset = array + (sizeof(SMU73_Discrete_GraphicsLevel) * i) 2598 + offsetof(SMU73_Discrete_GraphicsLevel, DownHyst); 2599 offset = up_hyst_offset & ~0x3; 2600 tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset)); 2601 tmp = phm_set_field_to_u32(up_hyst_offset, tmp, levels[i].UpHyst, sizeof(uint8_t)); 2602 tmp = phm_set_field_to_u32(down_hyst_offset, tmp, levels[i].DownHyst, sizeof(uint8_t)); 2603 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp)); 2604 } 2605 } 2606 if (!data->sclk_dpm_key_disabled) 2607 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_SCLKDPM_UnfreezeLevel); 2608 } 2609 2610 if (setting->bupdate_mclk) { 2611 if (!data->mclk_dpm_key_disabled) 2612 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_MCLKDPM_FreezeLevel); 2613 for (i = 0; i < smu_data->smc_state_table.MemoryDpmLevelCount; i++) { 2614 if (mclk_levels[i].ActivityLevel != 2615 cpu_to_be16(setting->mclk_activity)) { 2616 mclk_levels[i].ActivityLevel = cpu_to_be16(setting->mclk_activity); 2617 2618 clk_activity_offset = mclk_array + (sizeof(SMU73_Discrete_MemoryLevel) * i) 2619 + offsetof(SMU73_Discrete_MemoryLevel, ActivityLevel); 2620 offset = clk_activity_offset & ~0x3; 2621 tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset)); 2622 tmp = phm_set_field_to_u32(clk_activity_offset, tmp, mclk_levels[i].ActivityLevel, sizeof(uint16_t)); 2623 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp)); 2624 2625 } 2626 if (mclk_levels[i].UpHyst != setting->mclk_up_hyst || 2627 mclk_levels[i].DownHyst != setting->mclk_down_hyst) { 2628 mclk_levels[i].UpHyst = setting->mclk_up_hyst; 2629 mclk_levels[i].DownHyst = setting->mclk_down_hyst; 2630 up_hyst_offset = mclk_array + (sizeof(SMU73_Discrete_MemoryLevel) * i) 2631 + offsetof(SMU73_Discrete_MemoryLevel, UpHyst); 2632 down_hyst_offset = mclk_array + (sizeof(SMU73_Discrete_MemoryLevel) * i) 2633 + offsetof(SMU73_Discrete_MemoryLevel, DownHyst); 2634 offset = up_hyst_offset & ~0x3; 2635 tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset)); 2636 tmp = phm_set_field_to_u32(up_hyst_offset, tmp, mclk_levels[i].UpHyst, sizeof(uint8_t)); 2637 tmp = phm_set_field_to_u32(down_hyst_offset, tmp, mclk_levels[i].DownHyst, sizeof(uint8_t)); 2638 cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp)); 2639 } 2640 } 2641 if (!data->mclk_dpm_key_disabled) 2642 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_MCLKDPM_UnfreezeLevel); 2643 } 2644 return 0; 2645 } 2646 2647 const struct pp_smumgr_func fiji_smu_funcs = { 2648 .name = "fiji_smu", 2649 .smu_init = &fiji_smu_init, 2650 .smu_fini = &smu7_smu_fini, 2651 .start_smu = &fiji_start_smu, 2652 .check_fw_load_finish = &smu7_check_fw_load_finish, 2653 .request_smu_load_fw = &smu7_reload_firmware, 2654 .request_smu_load_specific_fw = NULL, 2655 .send_msg_to_smc = &smu7_send_msg_to_smc, 2656 .send_msg_to_smc_with_parameter = &smu7_send_msg_to_smc_with_parameter, 2657 .download_pptable_settings = NULL, 2658 .upload_pptable_settings = NULL, 2659 .update_smc_table = fiji_update_smc_table, 2660 .get_offsetof = fiji_get_offsetof, 2661 .process_firmware_header = fiji_process_firmware_header, 2662 .init_smc_table = fiji_init_smc_table, 2663 .update_sclk_threshold = fiji_update_sclk_threshold, 2664 .thermal_setup_fan_table = fiji_thermal_setup_fan_table, 2665 .thermal_avfs_enable = fiji_thermal_avfs_enable, 2666 .populate_all_graphic_levels = fiji_populate_all_graphic_levels, 2667 .populate_all_memory_levels = fiji_populate_all_memory_levels, 2668 .get_mac_definition = fiji_get_mac_definition, 2669 .initialize_mc_reg_table = fiji_initialize_mc_reg_table, 2670 .is_dpm_running = fiji_is_dpm_running, 2671 .is_hw_avfs_present = fiji_is_hw_avfs_present, 2672 .update_dpm_settings = fiji_update_dpm_settings, 2673 }; 2674