1 /* 2 * Copyright 2015 Advanced Micro Devices, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 * 22 */ 23 #include "pp_debug.h" 24 #include <linux/module.h> 25 #include <linux/slab.h> 26 27 #include "process_pptables_v1_0.h" 28 #include "ppatomctrl.h" 29 #include "atombios.h" 30 #include "hwmgr.h" 31 #include "cgs_common.h" 32 #include "pptable_v1_0.h" 33 34 /** 35 * Private Function used during initialization. 36 * @param hwmgr Pointer to the hardware manager. 37 * @param setIt A flag indication if the capability should be set (TRUE) or reset (FALSE). 38 * @param cap Which capability to set/reset. 39 */ 40 static void set_hw_cap(struct pp_hwmgr *hwmgr, bool setIt, enum phm_platform_caps cap) 41 { 42 if (setIt) 43 phm_cap_set(hwmgr->platform_descriptor.platformCaps, cap); 44 else 45 phm_cap_unset(hwmgr->platform_descriptor.platformCaps, cap); 46 } 47 48 49 /** 50 * Private Function used during initialization. 51 * @param hwmgr Pointer to the hardware manager. 52 * @param powerplay_caps the bit array (from BIOS) of capability bits. 53 * @exception the current implementation always returns 1. 54 */ 55 static int set_platform_caps(struct pp_hwmgr *hwmgr, uint32_t powerplay_caps) 56 { 57 PP_ASSERT_WITH_CODE((~powerplay_caps & ____RETIRE16____), 58 "ATOM_PP_PLATFORM_CAP_ASPM_L1 is not supported!", continue); 59 PP_ASSERT_WITH_CODE((~powerplay_caps & ____RETIRE64____), 60 "ATOM_PP_PLATFORM_CAP_GEMINIPRIMARY is not supported!", continue); 61 PP_ASSERT_WITH_CODE((~powerplay_caps & ____RETIRE512____), 62 "ATOM_PP_PLATFORM_CAP_SIDEPORTCONTROL is not supported!", continue); 63 PP_ASSERT_WITH_CODE((~powerplay_caps & ____RETIRE1024____), 64 "ATOM_PP_PLATFORM_CAP_TURNOFFPLL_ASPML1 is not supported!", continue); 65 PP_ASSERT_WITH_CODE((~powerplay_caps & ____RETIRE2048____), 66 "ATOM_PP_PLATFORM_CAP_HTLINKCONTROL is not supported!", continue); 67 68 set_hw_cap( 69 hwmgr, 70 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_POWERPLAY), 71 PHM_PlatformCaps_PowerPlaySupport 72 ); 73 74 set_hw_cap( 75 hwmgr, 76 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_SBIOSPOWERSOURCE), 77 PHM_PlatformCaps_BiosPowerSourceControl 78 ); 79 80 set_hw_cap( 81 hwmgr, 82 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_HARDWAREDC), 83 PHM_PlatformCaps_AutomaticDCTransition 84 ); 85 86 set_hw_cap( 87 hwmgr, 88 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_MVDD_CONTROL), 89 PHM_PlatformCaps_EnableMVDDControl 90 ); 91 92 set_hw_cap( 93 hwmgr, 94 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_VDDCI_CONTROL), 95 PHM_PlatformCaps_ControlVDDCI 96 ); 97 98 set_hw_cap( 99 hwmgr, 100 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_VDDGFX_CONTROL), 101 PHM_PlatformCaps_ControlVDDGFX 102 ); 103 104 set_hw_cap( 105 hwmgr, 106 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_BACO), 107 PHM_PlatformCaps_BACO 108 ); 109 110 set_hw_cap( 111 hwmgr, 112 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_DISABLE_VOLTAGE_ISLAND), 113 PHM_PlatformCaps_DisableVoltageIsland 114 ); 115 116 set_hw_cap( 117 hwmgr, 118 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_COMBINE_PCC_WITH_THERMAL_SIGNAL), 119 PHM_PlatformCaps_CombinePCCWithThermalSignal 120 ); 121 122 set_hw_cap( 123 hwmgr, 124 0 != (powerplay_caps & ATOM_TONGA_PLATFORM_LOAD_POST_PRODUCTION_FIRMWARE), 125 PHM_PlatformCaps_LoadPostProductionFirmware 126 ); 127 128 return 0; 129 } 130 131 /** 132 * Private Function to get the PowerPlay Table Address. 133 */ 134 static const void *get_powerplay_table(struct pp_hwmgr *hwmgr) 135 { 136 int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); 137 138 u16 size; 139 u8 frev, crev; 140 void *table_address = (void *)hwmgr->soft_pp_table; 141 142 if (!table_address) { 143 table_address = (ATOM_Tonga_POWERPLAYTABLE *) 144 smu_atom_get_data_table(hwmgr->adev, 145 index, &size, &frev, &crev); 146 hwmgr->soft_pp_table = table_address; /*Cache the result in RAM.*/ 147 hwmgr->soft_pp_table_size = size; 148 } 149 150 return table_address; 151 } 152 153 static int get_vddc_lookup_table( 154 struct pp_hwmgr *hwmgr, 155 phm_ppt_v1_voltage_lookup_table **lookup_table, 156 const ATOM_Tonga_Voltage_Lookup_Table *vddc_lookup_pp_tables, 157 uint32_t max_levels 158 ) 159 { 160 uint32_t table_size, i; 161 phm_ppt_v1_voltage_lookup_table *table; 162 phm_ppt_v1_voltage_lookup_record *record; 163 ATOM_Tonga_Voltage_Lookup_Record *atom_record; 164 165 PP_ASSERT_WITH_CODE((0 != vddc_lookup_pp_tables->ucNumEntries), 166 "Invalid CAC Leakage PowerPlay Table!", return 1); 167 168 table_size = sizeof(uint32_t) + 169 sizeof(phm_ppt_v1_voltage_lookup_record) * max_levels; 170 171 table = kzalloc(table_size, GFP_KERNEL); 172 173 if (NULL == table) 174 return -ENOMEM; 175 176 table->count = vddc_lookup_pp_tables->ucNumEntries; 177 178 for (i = 0; i < vddc_lookup_pp_tables->ucNumEntries; i++) { 179 record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( 180 phm_ppt_v1_voltage_lookup_record, 181 entries, table, i); 182 atom_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( 183 ATOM_Tonga_Voltage_Lookup_Record, 184 entries, vddc_lookup_pp_tables, i); 185 record->us_calculated = 0; 186 record->us_vdd = le16_to_cpu(atom_record->usVdd); 187 record->us_cac_low = le16_to_cpu(atom_record->usCACLow); 188 record->us_cac_mid = le16_to_cpu(atom_record->usCACMid); 189 record->us_cac_high = le16_to_cpu(atom_record->usCACHigh); 190 } 191 192 *lookup_table = table; 193 194 return 0; 195 } 196 197 /** 198 * Private Function used during initialization. 199 * Initialize Platform Power Management Parameter table 200 * @param hwmgr Pointer to the hardware manager. 201 * @param atom_ppm_table Pointer to PPM table in VBIOS 202 */ 203 static int get_platform_power_management_table( 204 struct pp_hwmgr *hwmgr, 205 ATOM_Tonga_PPM_Table *atom_ppm_table) 206 { 207 struct phm_ppm_table *ptr = kzalloc(sizeof(ATOM_Tonga_PPM_Table), GFP_KERNEL); 208 struct phm_ppt_v1_information *pp_table_information = 209 (struct phm_ppt_v1_information *)(hwmgr->pptable); 210 211 if (NULL == ptr) 212 return -ENOMEM; 213 214 ptr->ppm_design 215 = atom_ppm_table->ucPpmDesign; 216 ptr->cpu_core_number 217 = atom_ppm_table->usCpuCoreNumber; 218 ptr->platform_tdp 219 = atom_ppm_table->ulPlatformTDP; 220 ptr->small_ac_platform_tdp 221 = atom_ppm_table->ulSmallACPlatformTDP; 222 ptr->platform_tdc 223 = atom_ppm_table->ulPlatformTDC; 224 ptr->small_ac_platform_tdc 225 = atom_ppm_table->ulSmallACPlatformTDC; 226 ptr->apu_tdp 227 = atom_ppm_table->ulApuTDP; 228 ptr->dgpu_tdp 229 = atom_ppm_table->ulDGpuTDP; 230 ptr->dgpu_ulv_power 231 = atom_ppm_table->ulDGpuUlvPower; 232 ptr->tj_max 233 = atom_ppm_table->ulTjmax; 234 235 pp_table_information->ppm_parameter_table = ptr; 236 237 return 0; 238 } 239 240 /** 241 * Private Function used during initialization. 242 * Initialize TDP limits for DPM2 243 * @param hwmgr Pointer to the hardware manager. 244 * @param powerplay_table Pointer to the PowerPlay Table. 245 */ 246 static int init_dpm_2_parameters( 247 struct pp_hwmgr *hwmgr, 248 const ATOM_Tonga_POWERPLAYTABLE *powerplay_table 249 ) 250 { 251 int result = 0; 252 struct phm_ppt_v1_information *pp_table_information = (struct phm_ppt_v1_information *)(hwmgr->pptable); 253 ATOM_Tonga_PPM_Table *atom_ppm_table; 254 uint32_t disable_ppm = 0; 255 uint32_t disable_power_control = 0; 256 257 pp_table_information->us_ulv_voltage_offset = 258 le16_to_cpu(powerplay_table->usUlvVoltageOffset); 259 260 pp_table_information->ppm_parameter_table = NULL; 261 pp_table_information->vddc_lookup_table = NULL; 262 pp_table_information->vddgfx_lookup_table = NULL; 263 /* TDP limits */ 264 hwmgr->platform_descriptor.TDPODLimit = 265 le16_to_cpu(powerplay_table->usPowerControlLimit); 266 hwmgr->platform_descriptor.TDPAdjustment = 0; 267 hwmgr->platform_descriptor.VidAdjustment = 0; 268 hwmgr->platform_descriptor.VidAdjustmentPolarity = 0; 269 hwmgr->platform_descriptor.VidMinLimit = 0; 270 hwmgr->platform_descriptor.VidMaxLimit = 1500000; 271 hwmgr->platform_descriptor.VidStep = 6250; 272 273 disable_power_control = 0; 274 if (0 == disable_power_control) { 275 /* enable TDP overdrive (PowerControl) feature as well if supported */ 276 if (hwmgr->platform_descriptor.TDPODLimit != 0) 277 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 278 PHM_PlatformCaps_PowerControl); 279 } 280 281 if (0 != powerplay_table->usVddcLookupTableOffset) { 282 const ATOM_Tonga_Voltage_Lookup_Table *pVddcCACTable = 283 (ATOM_Tonga_Voltage_Lookup_Table *)(((unsigned long)powerplay_table) + 284 le16_to_cpu(powerplay_table->usVddcLookupTableOffset)); 285 286 result = get_vddc_lookup_table(hwmgr, 287 &pp_table_information->vddc_lookup_table, pVddcCACTable, 16); 288 } 289 290 if (0 != powerplay_table->usVddgfxLookupTableOffset) { 291 const ATOM_Tonga_Voltage_Lookup_Table *pVddgfxCACTable = 292 (ATOM_Tonga_Voltage_Lookup_Table *)(((unsigned long)powerplay_table) + 293 le16_to_cpu(powerplay_table->usVddgfxLookupTableOffset)); 294 295 result = get_vddc_lookup_table(hwmgr, 296 &pp_table_information->vddgfx_lookup_table, pVddgfxCACTable, 16); 297 } 298 299 disable_ppm = 0; 300 if (0 == disable_ppm) { 301 atom_ppm_table = (ATOM_Tonga_PPM_Table *) 302 (((unsigned long)powerplay_table) + le16_to_cpu(powerplay_table->usPPMTableOffset)); 303 304 if (0 != powerplay_table->usPPMTableOffset) { 305 if (get_platform_power_management_table(hwmgr, atom_ppm_table) == 0) { 306 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 307 PHM_PlatformCaps_EnablePlatformPowerManagement); 308 } 309 } 310 } 311 312 return result; 313 } 314 315 static int get_valid_clk( 316 struct pp_hwmgr *hwmgr, 317 struct phm_clock_array **clk_table, 318 phm_ppt_v1_clock_voltage_dependency_table const *clk_volt_pp_table 319 ) 320 { 321 uint32_t table_size, i; 322 struct phm_clock_array *table; 323 phm_ppt_v1_clock_voltage_dependency_record *dep_record; 324 325 PP_ASSERT_WITH_CODE((0 != clk_volt_pp_table->count), 326 "Invalid PowerPlay Table!", return -1); 327 328 table_size = sizeof(uint32_t) + 329 sizeof(uint32_t) * clk_volt_pp_table->count; 330 331 table = kzalloc(table_size, GFP_KERNEL); 332 333 if (NULL == table) 334 return -ENOMEM; 335 336 table->count = (uint32_t)clk_volt_pp_table->count; 337 338 for (i = 0; i < table->count; i++) { 339 dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( 340 phm_ppt_v1_clock_voltage_dependency_record, 341 entries, clk_volt_pp_table, i); 342 table->values[i] = (uint32_t)dep_record->clk; 343 } 344 *clk_table = table; 345 346 return 0; 347 } 348 349 static int get_hard_limits( 350 struct pp_hwmgr *hwmgr, 351 struct phm_clock_and_voltage_limits *limits, 352 ATOM_Tonga_Hard_Limit_Table const *limitable 353 ) 354 { 355 PP_ASSERT_WITH_CODE((0 != limitable->ucNumEntries), "Invalid PowerPlay Table!", return -1); 356 357 /* currently we always take entries[0] parameters */ 358 limits->sclk = (uint32_t)limitable->entries[0].ulSCLKLimit; 359 limits->mclk = (uint32_t)limitable->entries[0].ulMCLKLimit; 360 limits->vddc = (uint16_t)limitable->entries[0].usVddcLimit; 361 limits->vddci = (uint16_t)limitable->entries[0].usVddciLimit; 362 limits->vddgfx = (uint16_t)limitable->entries[0].usVddgfxLimit; 363 364 return 0; 365 } 366 367 static int get_mclk_voltage_dependency_table( 368 struct pp_hwmgr *hwmgr, 369 phm_ppt_v1_clock_voltage_dependency_table **pp_tonga_mclk_dep_table, 370 ATOM_Tonga_MCLK_Dependency_Table const *mclk_dep_table 371 ) 372 { 373 uint32_t table_size, i; 374 phm_ppt_v1_clock_voltage_dependency_table *mclk_table; 375 phm_ppt_v1_clock_voltage_dependency_record *mclk_table_record; 376 ATOM_Tonga_MCLK_Dependency_Record *mclk_dep_record; 377 378 PP_ASSERT_WITH_CODE((0 != mclk_dep_table->ucNumEntries), 379 "Invalid PowerPlay Table!", return -1); 380 381 table_size = sizeof(uint32_t) + sizeof(phm_ppt_v1_clock_voltage_dependency_record) 382 * mclk_dep_table->ucNumEntries; 383 384 mclk_table = kzalloc(table_size, GFP_KERNEL); 385 386 if (NULL == mclk_table) 387 return -ENOMEM; 388 389 mclk_table->count = (uint32_t)mclk_dep_table->ucNumEntries; 390 391 for (i = 0; i < mclk_dep_table->ucNumEntries; i++) { 392 mclk_table_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( 393 phm_ppt_v1_clock_voltage_dependency_record, 394 entries, mclk_table, i); 395 mclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( 396 ATOM_Tonga_MCLK_Dependency_Record, 397 entries, mclk_dep_table, i); 398 mclk_table_record->vddInd = mclk_dep_record->ucVddcInd; 399 mclk_table_record->vdd_offset = mclk_dep_record->usVddgfxOffset; 400 mclk_table_record->vddci = mclk_dep_record->usVddci; 401 mclk_table_record->mvdd = mclk_dep_record->usMvdd; 402 mclk_table_record->clk = mclk_dep_record->ulMclk; 403 } 404 405 *pp_tonga_mclk_dep_table = mclk_table; 406 407 return 0; 408 } 409 410 static int get_sclk_voltage_dependency_table( 411 struct pp_hwmgr *hwmgr, 412 phm_ppt_v1_clock_voltage_dependency_table **pp_tonga_sclk_dep_table, 413 PPTable_Generic_SubTable_Header const *sclk_dep_table 414 ) 415 { 416 uint32_t table_size, i; 417 phm_ppt_v1_clock_voltage_dependency_table *sclk_table; 418 phm_ppt_v1_clock_voltage_dependency_record *sclk_table_record; 419 420 if (sclk_dep_table->ucRevId < 1) { 421 const ATOM_Tonga_SCLK_Dependency_Table *tonga_table = 422 (ATOM_Tonga_SCLK_Dependency_Table *)sclk_dep_table; 423 ATOM_Tonga_SCLK_Dependency_Record *sclk_dep_record; 424 425 PP_ASSERT_WITH_CODE((0 != tonga_table->ucNumEntries), 426 "Invalid PowerPlay Table!", return -1); 427 428 table_size = sizeof(uint32_t) + sizeof(phm_ppt_v1_clock_voltage_dependency_record) 429 * tonga_table->ucNumEntries; 430 431 sclk_table = kzalloc(table_size, GFP_KERNEL); 432 433 if (NULL == sclk_table) 434 return -ENOMEM; 435 436 sclk_table->count = (uint32_t)tonga_table->ucNumEntries; 437 438 for (i = 0; i < tonga_table->ucNumEntries; i++) { 439 sclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( 440 ATOM_Tonga_SCLK_Dependency_Record, 441 entries, tonga_table, i); 442 sclk_table_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( 443 phm_ppt_v1_clock_voltage_dependency_record, 444 entries, sclk_table, i); 445 sclk_table_record->vddInd = sclk_dep_record->ucVddInd; 446 sclk_table_record->vdd_offset = sclk_dep_record->usVddcOffset; 447 sclk_table_record->clk = sclk_dep_record->ulSclk; 448 sclk_table_record->cks_enable = 449 (((sclk_dep_record->ucCKSVOffsetandDisable & 0x80) >> 7) == 0) ? 1 : 0; 450 sclk_table_record->cks_voffset = (sclk_dep_record->ucCKSVOffsetandDisable & 0x7F); 451 } 452 } else { 453 const ATOM_Polaris_SCLK_Dependency_Table *polaris_table = 454 (ATOM_Polaris_SCLK_Dependency_Table *)sclk_dep_table; 455 ATOM_Polaris_SCLK_Dependency_Record *sclk_dep_record; 456 457 PP_ASSERT_WITH_CODE((0 != polaris_table->ucNumEntries), 458 "Invalid PowerPlay Table!", return -1); 459 460 table_size = sizeof(uint32_t) + sizeof(phm_ppt_v1_clock_voltage_dependency_record) 461 * polaris_table->ucNumEntries; 462 463 sclk_table = kzalloc(table_size, GFP_KERNEL); 464 465 if (NULL == sclk_table) 466 return -ENOMEM; 467 468 sclk_table->count = (uint32_t)polaris_table->ucNumEntries; 469 470 for (i = 0; i < polaris_table->ucNumEntries; i++) { 471 sclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( 472 ATOM_Polaris_SCLK_Dependency_Record, 473 entries, polaris_table, i); 474 sclk_table_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( 475 phm_ppt_v1_clock_voltage_dependency_record, 476 entries, sclk_table, i); 477 sclk_table_record->vddInd = sclk_dep_record->ucVddInd; 478 sclk_table_record->vdd_offset = sclk_dep_record->usVddcOffset; 479 sclk_table_record->clk = sclk_dep_record->ulSclk; 480 sclk_table_record->cks_enable = 481 (((sclk_dep_record->ucCKSVOffsetandDisable & 0x80) >> 7) == 0) ? 1 : 0; 482 sclk_table_record->cks_voffset = (sclk_dep_record->ucCKSVOffsetandDisable & 0x7F); 483 sclk_table_record->sclk_offset = sclk_dep_record->ulSclkOffset; 484 } 485 } 486 *pp_tonga_sclk_dep_table = sclk_table; 487 488 return 0; 489 } 490 491 static int get_pcie_table( 492 struct pp_hwmgr *hwmgr, 493 phm_ppt_v1_pcie_table **pp_tonga_pcie_table, 494 PPTable_Generic_SubTable_Header const *ptable 495 ) 496 { 497 uint32_t table_size, i, pcie_count; 498 phm_ppt_v1_pcie_table *pcie_table; 499 struct phm_ppt_v1_information *pp_table_information = 500 (struct phm_ppt_v1_information *)(hwmgr->pptable); 501 phm_ppt_v1_pcie_record *pcie_record; 502 503 if (ptable->ucRevId < 1) { 504 const ATOM_Tonga_PCIE_Table *atom_pcie_table = (ATOM_Tonga_PCIE_Table *)ptable; 505 ATOM_Tonga_PCIE_Record *atom_pcie_record; 506 507 PP_ASSERT_WITH_CODE((atom_pcie_table->ucNumEntries != 0), 508 "Invalid PowerPlay Table!", return -1); 509 510 table_size = sizeof(uint32_t) + 511 sizeof(phm_ppt_v1_pcie_record) * atom_pcie_table->ucNumEntries; 512 513 pcie_table = kzalloc(table_size, GFP_KERNEL); 514 515 if (pcie_table == NULL) 516 return -ENOMEM; 517 518 /* 519 * Make sure the number of pcie entries are less than or equal to sclk dpm levels. 520 * Since first PCIE entry is for ULV, #pcie has to be <= SclkLevel + 1. 521 */ 522 pcie_count = (pp_table_information->vdd_dep_on_sclk->count) + 1; 523 if ((uint32_t)atom_pcie_table->ucNumEntries <= pcie_count) 524 pcie_count = (uint32_t)atom_pcie_table->ucNumEntries; 525 else 526 pr_err("Number of Pcie Entries exceed the number of SCLK Dpm Levels! Disregarding the excess entries...\n"); 527 528 pcie_table->count = pcie_count; 529 for (i = 0; i < pcie_count; i++) { 530 pcie_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( 531 phm_ppt_v1_pcie_record, 532 entries, pcie_table, i); 533 atom_pcie_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( 534 ATOM_Tonga_PCIE_Record, 535 entries, atom_pcie_table, i); 536 pcie_record->gen_speed = atom_pcie_record->ucPCIEGenSpeed; 537 pcie_record->lane_width = atom_pcie_record->usPCIELaneWidth; 538 } 539 540 *pp_tonga_pcie_table = pcie_table; 541 } else { 542 /* Polaris10/Polaris11 and newer. */ 543 const ATOM_Polaris10_PCIE_Table *atom_pcie_table = (ATOM_Polaris10_PCIE_Table *)ptable; 544 ATOM_Polaris10_PCIE_Record *atom_pcie_record; 545 546 PP_ASSERT_WITH_CODE((atom_pcie_table->ucNumEntries != 0), 547 "Invalid PowerPlay Table!", return -1); 548 549 table_size = sizeof(uint32_t) + 550 sizeof(phm_ppt_v1_pcie_record) * atom_pcie_table->ucNumEntries; 551 552 pcie_table = kzalloc(table_size, GFP_KERNEL); 553 554 if (pcie_table == NULL) 555 return -ENOMEM; 556 557 /* 558 * Make sure the number of pcie entries are less than or equal to sclk dpm levels. 559 * Since first PCIE entry is for ULV, #pcie has to be <= SclkLevel + 1. 560 */ 561 pcie_count = (pp_table_information->vdd_dep_on_sclk->count) + 1; 562 if ((uint32_t)atom_pcie_table->ucNumEntries <= pcie_count) 563 pcie_count = (uint32_t)atom_pcie_table->ucNumEntries; 564 else 565 pr_err("Number of Pcie Entries exceed the number of SCLK Dpm Levels! Disregarding the excess entries...\n"); 566 567 pcie_table->count = pcie_count; 568 569 for (i = 0; i < pcie_count; i++) { 570 pcie_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( 571 phm_ppt_v1_pcie_record, 572 entries, pcie_table, i); 573 atom_pcie_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( 574 ATOM_Polaris10_PCIE_Record, 575 entries, atom_pcie_table, i); 576 pcie_record->gen_speed = atom_pcie_record->ucPCIEGenSpeed; 577 pcie_record->lane_width = atom_pcie_record->usPCIELaneWidth; 578 pcie_record->pcie_sclk = atom_pcie_record->ulPCIE_Sclk; 579 } 580 581 *pp_tonga_pcie_table = pcie_table; 582 } 583 584 return 0; 585 } 586 587 static int get_cac_tdp_table( 588 struct pp_hwmgr *hwmgr, 589 struct phm_cac_tdp_table **cac_tdp_table, 590 const PPTable_Generic_SubTable_Header * table 591 ) 592 { 593 uint32_t table_size; 594 struct phm_cac_tdp_table *tdp_table; 595 596 table_size = sizeof(uint32_t) + sizeof(struct phm_cac_tdp_table); 597 tdp_table = kzalloc(table_size, GFP_KERNEL); 598 599 if (NULL == tdp_table) 600 return -ENOMEM; 601 602 hwmgr->dyn_state.cac_dtp_table = kzalloc(table_size, GFP_KERNEL); 603 604 if (NULL == hwmgr->dyn_state.cac_dtp_table) { 605 kfree(tdp_table); 606 return -ENOMEM; 607 } 608 609 if (table->ucRevId < 3) { 610 const ATOM_Tonga_PowerTune_Table *tonga_table = 611 (ATOM_Tonga_PowerTune_Table *)table; 612 tdp_table->usTDP = tonga_table->usTDP; 613 tdp_table->usConfigurableTDP = 614 tonga_table->usConfigurableTDP; 615 tdp_table->usTDC = tonga_table->usTDC; 616 tdp_table->usBatteryPowerLimit = 617 tonga_table->usBatteryPowerLimit; 618 tdp_table->usSmallPowerLimit = 619 tonga_table->usSmallPowerLimit; 620 tdp_table->usLowCACLeakage = 621 tonga_table->usLowCACLeakage; 622 tdp_table->usHighCACLeakage = 623 tonga_table->usHighCACLeakage; 624 tdp_table->usMaximumPowerDeliveryLimit = 625 tonga_table->usMaximumPowerDeliveryLimit; 626 tdp_table->usDefaultTargetOperatingTemp = 627 tonga_table->usTjMax; 628 tdp_table->usTargetOperatingTemp = 629 tonga_table->usTjMax; /*Set the initial temp to the same as default */ 630 tdp_table->usPowerTuneDataSetID = 631 tonga_table->usPowerTuneDataSetID; 632 tdp_table->usSoftwareShutdownTemp = 633 tonga_table->usSoftwareShutdownTemp; 634 tdp_table->usClockStretchAmount = 635 tonga_table->usClockStretchAmount; 636 } else { /* Fiji and newer */ 637 const ATOM_Fiji_PowerTune_Table *fijitable = 638 (ATOM_Fiji_PowerTune_Table *)table; 639 tdp_table->usTDP = fijitable->usTDP; 640 tdp_table->usConfigurableTDP = fijitable->usConfigurableTDP; 641 tdp_table->usTDC = fijitable->usTDC; 642 tdp_table->usBatteryPowerLimit = fijitable->usBatteryPowerLimit; 643 tdp_table->usSmallPowerLimit = fijitable->usSmallPowerLimit; 644 tdp_table->usLowCACLeakage = fijitable->usLowCACLeakage; 645 tdp_table->usHighCACLeakage = fijitable->usHighCACLeakage; 646 tdp_table->usMaximumPowerDeliveryLimit = 647 fijitable->usMaximumPowerDeliveryLimit; 648 tdp_table->usDefaultTargetOperatingTemp = 649 fijitable->usTjMax; 650 tdp_table->usTargetOperatingTemp = 651 fijitable->usTjMax; /*Set the initial temp to the same as default */ 652 tdp_table->usPowerTuneDataSetID = 653 fijitable->usPowerTuneDataSetID; 654 tdp_table->usSoftwareShutdownTemp = 655 fijitable->usSoftwareShutdownTemp; 656 tdp_table->usClockStretchAmount = 657 fijitable->usClockStretchAmount; 658 tdp_table->usTemperatureLimitHotspot = 659 fijitable->usTemperatureLimitHotspot; 660 tdp_table->usTemperatureLimitLiquid1 = 661 fijitable->usTemperatureLimitLiquid1; 662 tdp_table->usTemperatureLimitLiquid2 = 663 fijitable->usTemperatureLimitLiquid2; 664 tdp_table->usTemperatureLimitVrVddc = 665 fijitable->usTemperatureLimitVrVddc; 666 tdp_table->usTemperatureLimitVrMvdd = 667 fijitable->usTemperatureLimitVrMvdd; 668 tdp_table->usTemperatureLimitPlx = 669 fijitable->usTemperatureLimitPlx; 670 tdp_table->ucLiquid1_I2C_address = 671 fijitable->ucLiquid1_I2C_address; 672 tdp_table->ucLiquid2_I2C_address = 673 fijitable->ucLiquid2_I2C_address; 674 tdp_table->ucLiquid_I2C_Line = 675 fijitable->ucLiquid_I2C_Line; 676 tdp_table->ucVr_I2C_address = fijitable->ucVr_I2C_address; 677 tdp_table->ucVr_I2C_Line = fijitable->ucVr_I2C_Line; 678 tdp_table->ucPlx_I2C_address = fijitable->ucPlx_I2C_address; 679 tdp_table->ucPlx_I2C_Line = fijitable->ucPlx_I2C_Line; 680 } 681 682 *cac_tdp_table = tdp_table; 683 684 return 0; 685 } 686 687 static int get_mm_clock_voltage_table( 688 struct pp_hwmgr *hwmgr, 689 phm_ppt_v1_mm_clock_voltage_dependency_table **tonga_mm_table, 690 const ATOM_Tonga_MM_Dependency_Table * mm_dependency_table 691 ) 692 { 693 uint32_t table_size, i; 694 const ATOM_Tonga_MM_Dependency_Record *mm_dependency_record; 695 phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table; 696 phm_ppt_v1_mm_clock_voltage_dependency_record *mm_table_record; 697 698 PP_ASSERT_WITH_CODE((0 != mm_dependency_table->ucNumEntries), 699 "Invalid PowerPlay Table!", return -1); 700 table_size = sizeof(uint32_t) + 701 sizeof(phm_ppt_v1_mm_clock_voltage_dependency_record) 702 * mm_dependency_table->ucNumEntries; 703 mm_table = kzalloc(table_size, GFP_KERNEL); 704 705 if (NULL == mm_table) 706 return -ENOMEM; 707 708 mm_table->count = mm_dependency_table->ucNumEntries; 709 710 for (i = 0; i < mm_dependency_table->ucNumEntries; i++) { 711 mm_dependency_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( 712 ATOM_Tonga_MM_Dependency_Record, 713 entries, mm_dependency_table, i); 714 mm_table_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( 715 phm_ppt_v1_mm_clock_voltage_dependency_record, 716 entries, mm_table, i); 717 mm_table_record->vddcInd = mm_dependency_record->ucVddcInd; 718 mm_table_record->vddgfx_offset = mm_dependency_record->usVddgfxOffset; 719 mm_table_record->aclk = mm_dependency_record->ulAClk; 720 mm_table_record->samclock = mm_dependency_record->ulSAMUClk; 721 mm_table_record->eclk = mm_dependency_record->ulEClk; 722 mm_table_record->vclk = mm_dependency_record->ulVClk; 723 mm_table_record->dclk = mm_dependency_record->ulDClk; 724 } 725 726 *tonga_mm_table = mm_table; 727 728 return 0; 729 } 730 731 static int get_gpio_table(struct pp_hwmgr *hwmgr, 732 struct phm_ppt_v1_gpio_table **pp_tonga_gpio_table, 733 const ATOM_Tonga_GPIO_Table *atom_gpio_table) 734 { 735 uint32_t table_size; 736 struct phm_ppt_v1_gpio_table *pp_gpio_table; 737 struct phm_ppt_v1_information *pp_table_information = 738 (struct phm_ppt_v1_information *)(hwmgr->pptable); 739 740 table_size = sizeof(struct phm_ppt_v1_gpio_table); 741 pp_gpio_table = kzalloc(table_size, GFP_KERNEL); 742 if (!pp_gpio_table) 743 return -ENOMEM; 744 745 if (pp_table_information->vdd_dep_on_sclk->count < 746 atom_gpio_table->ucVRHotTriggeredSclkDpmIndex) 747 PP_ASSERT_WITH_CODE(false, 748 "SCLK DPM index for VRHot cannot exceed the total sclk level count!",); 749 else 750 pp_gpio_table->vrhot_triggered_sclk_dpm_index = 751 atom_gpio_table->ucVRHotTriggeredSclkDpmIndex; 752 753 *pp_tonga_gpio_table = pp_gpio_table; 754 755 return 0; 756 } 757 /** 758 * Private Function used during initialization. 759 * Initialize clock voltage dependency 760 * @param hwmgr Pointer to the hardware manager. 761 * @param powerplay_table Pointer to the PowerPlay Table. 762 */ 763 static int init_clock_voltage_dependency( 764 struct pp_hwmgr *hwmgr, 765 const ATOM_Tonga_POWERPLAYTABLE *powerplay_table 766 ) 767 { 768 int result = 0; 769 struct phm_ppt_v1_information *pp_table_information = 770 (struct phm_ppt_v1_information *)(hwmgr->pptable); 771 772 const ATOM_Tonga_MM_Dependency_Table *mm_dependency_table = 773 (const ATOM_Tonga_MM_Dependency_Table *)(((unsigned long) powerplay_table) + 774 le16_to_cpu(powerplay_table->usMMDependencyTableOffset)); 775 const PPTable_Generic_SubTable_Header *pPowerTuneTable = 776 (const PPTable_Generic_SubTable_Header *)(((unsigned long) powerplay_table) + 777 le16_to_cpu(powerplay_table->usPowerTuneTableOffset)); 778 const ATOM_Tonga_MCLK_Dependency_Table *mclk_dep_table = 779 (const ATOM_Tonga_MCLK_Dependency_Table *)(((unsigned long) powerplay_table) + 780 le16_to_cpu(powerplay_table->usMclkDependencyTableOffset)); 781 const PPTable_Generic_SubTable_Header *sclk_dep_table = 782 (const PPTable_Generic_SubTable_Header *)(((unsigned long) powerplay_table) + 783 le16_to_cpu(powerplay_table->usSclkDependencyTableOffset)); 784 const ATOM_Tonga_Hard_Limit_Table *pHardLimits = 785 (const ATOM_Tonga_Hard_Limit_Table *)(((unsigned long) powerplay_table) + 786 le16_to_cpu(powerplay_table->usHardLimitTableOffset)); 787 const PPTable_Generic_SubTable_Header *pcie_table = 788 (const PPTable_Generic_SubTable_Header *)(((unsigned long) powerplay_table) + 789 le16_to_cpu(powerplay_table->usPCIETableOffset)); 790 const ATOM_Tonga_GPIO_Table *gpio_table = 791 (const ATOM_Tonga_GPIO_Table *)(((unsigned long) powerplay_table) + 792 le16_to_cpu(powerplay_table->usGPIOTableOffset)); 793 794 pp_table_information->vdd_dep_on_sclk = NULL; 795 pp_table_information->vdd_dep_on_mclk = NULL; 796 pp_table_information->mm_dep_table = NULL; 797 pp_table_information->pcie_table = NULL; 798 pp_table_information->gpio_table = NULL; 799 800 if (powerplay_table->usMMDependencyTableOffset != 0) 801 result = get_mm_clock_voltage_table(hwmgr, 802 &pp_table_information->mm_dep_table, mm_dependency_table); 803 804 if (result == 0 && powerplay_table->usPowerTuneTableOffset != 0) 805 result = get_cac_tdp_table(hwmgr, 806 &pp_table_information->cac_dtp_table, pPowerTuneTable); 807 808 if (result == 0 && powerplay_table->usSclkDependencyTableOffset != 0) 809 result = get_sclk_voltage_dependency_table(hwmgr, 810 &pp_table_information->vdd_dep_on_sclk, sclk_dep_table); 811 812 if (result == 0 && powerplay_table->usMclkDependencyTableOffset != 0) 813 result = get_mclk_voltage_dependency_table(hwmgr, 814 &pp_table_information->vdd_dep_on_mclk, mclk_dep_table); 815 816 if (result == 0 && powerplay_table->usPCIETableOffset != 0) 817 result = get_pcie_table(hwmgr, 818 &pp_table_information->pcie_table, pcie_table); 819 820 if (result == 0 && powerplay_table->usHardLimitTableOffset != 0) 821 result = get_hard_limits(hwmgr, 822 &pp_table_information->max_clock_voltage_on_dc, pHardLimits); 823 824 hwmgr->dyn_state.max_clock_voltage_on_dc.sclk = 825 pp_table_information->max_clock_voltage_on_dc.sclk; 826 hwmgr->dyn_state.max_clock_voltage_on_dc.mclk = 827 pp_table_information->max_clock_voltage_on_dc.mclk; 828 hwmgr->dyn_state.max_clock_voltage_on_dc.vddc = 829 pp_table_information->max_clock_voltage_on_dc.vddc; 830 hwmgr->dyn_state.max_clock_voltage_on_dc.vddci = 831 pp_table_information->max_clock_voltage_on_dc.vddci; 832 833 if (result == 0 && (NULL != pp_table_information->vdd_dep_on_mclk) 834 && (0 != pp_table_information->vdd_dep_on_mclk->count)) 835 result = get_valid_clk(hwmgr, &pp_table_information->valid_mclk_values, 836 pp_table_information->vdd_dep_on_mclk); 837 838 if (result == 0 && (NULL != pp_table_information->vdd_dep_on_sclk) 839 && (0 != pp_table_information->vdd_dep_on_sclk->count)) 840 result = get_valid_clk(hwmgr, &pp_table_information->valid_sclk_values, 841 pp_table_information->vdd_dep_on_sclk); 842 843 if (!result && gpio_table) 844 result = get_gpio_table(hwmgr, &pp_table_information->gpio_table, 845 gpio_table); 846 847 return result; 848 } 849 850 /** Retrieves the (signed) Overdrive limits from VBIOS. 851 * The max engine clock, memory clock and max temperature come from the firmware info table. 852 * 853 * The information is placed into the platform descriptor. 854 * 855 * @param hwmgr source of the VBIOS table and owner of the platform descriptor to be updated. 856 * @param powerplay_table the address of the PowerPlay table. 857 * 858 * @return 1 as long as the firmware info table was present and of a supported version. 859 */ 860 static int init_over_drive_limits( 861 struct pp_hwmgr *hwmgr, 862 const ATOM_Tonga_POWERPLAYTABLE *powerplay_table) 863 { 864 hwmgr->platform_descriptor.overdriveLimit.engineClock = 865 le32_to_cpu(powerplay_table->ulMaxODEngineClock); 866 hwmgr->platform_descriptor.overdriveLimit.memoryClock = 867 le32_to_cpu(powerplay_table->ulMaxODMemoryClock); 868 869 hwmgr->platform_descriptor.minOverdriveVDDC = 0; 870 hwmgr->platform_descriptor.maxOverdriveVDDC = 0; 871 hwmgr->platform_descriptor.overdriveVDDCStep = 0; 872 873 return 0; 874 } 875 876 /** 877 * Private Function used during initialization. 878 * Inspect the PowerPlay table for obvious signs of corruption. 879 * @param hwmgr Pointer to the hardware manager. 880 * @param powerplay_table Pointer to the PowerPlay Table. 881 * @exception This implementation always returns 1. 882 */ 883 static int init_thermal_controller( 884 struct pp_hwmgr *hwmgr, 885 const ATOM_Tonga_POWERPLAYTABLE *powerplay_table 886 ) 887 { 888 const PPTable_Generic_SubTable_Header *fan_table; 889 ATOM_Tonga_Thermal_Controller *thermal_controller; 890 891 thermal_controller = (ATOM_Tonga_Thermal_Controller *) 892 (((unsigned long)powerplay_table) + 893 le16_to_cpu(powerplay_table->usThermalControllerOffset)); 894 PP_ASSERT_WITH_CODE((0 != powerplay_table->usThermalControllerOffset), 895 "Thermal controller table not set!", return -1); 896 897 hwmgr->thermal_controller.ucType = thermal_controller->ucType; 898 hwmgr->thermal_controller.ucI2cLine = thermal_controller->ucI2cLine; 899 hwmgr->thermal_controller.ucI2cAddress = thermal_controller->ucI2cAddress; 900 901 hwmgr->thermal_controller.fanInfo.bNoFan = 902 (0 != (thermal_controller->ucFanParameters & ATOM_TONGA_PP_FANPARAMETERS_NOFAN)); 903 904 hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution = 905 thermal_controller->ucFanParameters & 906 ATOM_TONGA_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK; 907 908 hwmgr->thermal_controller.fanInfo.ulMinRPM 909 = thermal_controller->ucFanMinRPM * 100UL; 910 hwmgr->thermal_controller.fanInfo.ulMaxRPM 911 = thermal_controller->ucFanMaxRPM * 100UL; 912 913 set_hw_cap( 914 hwmgr, 915 ATOM_TONGA_PP_THERMALCONTROLLER_NONE != hwmgr->thermal_controller.ucType, 916 PHM_PlatformCaps_ThermalController 917 ); 918 919 if (0 == powerplay_table->usFanTableOffset) { 920 hwmgr->thermal_controller.use_hw_fan_control = 1; 921 return 0; 922 } 923 924 fan_table = (const PPTable_Generic_SubTable_Header *) 925 (((unsigned long)powerplay_table) + 926 le16_to_cpu(powerplay_table->usFanTableOffset)); 927 928 PP_ASSERT_WITH_CODE((0 != powerplay_table->usFanTableOffset), 929 "Fan table not set!", return -1); 930 PP_ASSERT_WITH_CODE((0 < fan_table->ucRevId), 931 "Unsupported fan table format!", return -1); 932 933 hwmgr->thermal_controller.advanceFanControlParameters.ulCycleDelay 934 = 100000; 935 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 936 PHM_PlatformCaps_MicrocodeFanControl); 937 938 if (fan_table->ucRevId < 8) { 939 const ATOM_Tonga_Fan_Table *tonga_fan_table = 940 (ATOM_Tonga_Fan_Table *)fan_table; 941 hwmgr->thermal_controller.advanceFanControlParameters.ucTHyst 942 = tonga_fan_table->ucTHyst; 943 hwmgr->thermal_controller.advanceFanControlParameters.usTMin 944 = tonga_fan_table->usTMin; 945 hwmgr->thermal_controller.advanceFanControlParameters.usTMed 946 = tonga_fan_table->usTMed; 947 hwmgr->thermal_controller.advanceFanControlParameters.usTHigh 948 = tonga_fan_table->usTHigh; 949 hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin 950 = tonga_fan_table->usPWMMin; 951 hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed 952 = tonga_fan_table->usPWMMed; 953 hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh 954 = tonga_fan_table->usPWMHigh; 955 hwmgr->thermal_controller.advanceFanControlParameters.usTMax 956 = 10900; /* hard coded */ 957 hwmgr->thermal_controller.advanceFanControlParameters.usTMax 958 = tonga_fan_table->usTMax; 959 hwmgr->thermal_controller.advanceFanControlParameters.ucFanControlMode 960 = tonga_fan_table->ucFanControlMode; 961 hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanPWM 962 = tonga_fan_table->usFanPWMMax; 963 hwmgr->thermal_controller.advanceFanControlParameters.usDefaultFanOutputSensitivity 964 = 4836; 965 hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity 966 = tonga_fan_table->usFanOutputSensitivity; 967 hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanRPM 968 = tonga_fan_table->usFanRPMMax; 969 hwmgr->thermal_controller.advanceFanControlParameters.ulMinFanSCLKAcousticLimit 970 = (tonga_fan_table->ulMinFanSCLKAcousticLimit / 100); /* PPTable stores it in 10Khz unit for 2 decimal places. SMC wants MHz. */ 971 hwmgr->thermal_controller.advanceFanControlParameters.ucTargetTemperature 972 = tonga_fan_table->ucTargetTemperature; 973 hwmgr->thermal_controller.advanceFanControlParameters.ucMinimumPWMLimit 974 = tonga_fan_table->ucMinimumPWMLimit; 975 } else { 976 const ATOM_Fiji_Fan_Table *fiji_fan_table = 977 (ATOM_Fiji_Fan_Table *)fan_table; 978 hwmgr->thermal_controller.advanceFanControlParameters.ucTHyst 979 = fiji_fan_table->ucTHyst; 980 hwmgr->thermal_controller.advanceFanControlParameters.usTMin 981 = fiji_fan_table->usTMin; 982 hwmgr->thermal_controller.advanceFanControlParameters.usTMed 983 = fiji_fan_table->usTMed; 984 hwmgr->thermal_controller.advanceFanControlParameters.usTHigh 985 = fiji_fan_table->usTHigh; 986 hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin 987 = fiji_fan_table->usPWMMin; 988 hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed 989 = fiji_fan_table->usPWMMed; 990 hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh 991 = fiji_fan_table->usPWMHigh; 992 hwmgr->thermal_controller.advanceFanControlParameters.usTMax 993 = fiji_fan_table->usTMax; 994 hwmgr->thermal_controller.advanceFanControlParameters.ucFanControlMode 995 = fiji_fan_table->ucFanControlMode; 996 hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanPWM 997 = fiji_fan_table->usFanPWMMax; 998 hwmgr->thermal_controller.advanceFanControlParameters.usDefaultFanOutputSensitivity 999 = 4836; 1000 hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity 1001 = fiji_fan_table->usFanOutputSensitivity; 1002 hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanRPM 1003 = fiji_fan_table->usFanRPMMax; 1004 hwmgr->thermal_controller.advanceFanControlParameters.ulMinFanSCLKAcousticLimit 1005 = (fiji_fan_table->ulMinFanSCLKAcousticLimit / 100); /* PPTable stores it in 10Khz unit for 2 decimal places. SMC wants MHz. */ 1006 hwmgr->thermal_controller.advanceFanControlParameters.ucTargetTemperature 1007 = fiji_fan_table->ucTargetTemperature; 1008 hwmgr->thermal_controller.advanceFanControlParameters.ucMinimumPWMLimit 1009 = fiji_fan_table->ucMinimumPWMLimit; 1010 1011 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainEdge 1012 = fiji_fan_table->usFanGainEdge; 1013 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainHotspot 1014 = fiji_fan_table->usFanGainHotspot; 1015 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainLiquid 1016 = fiji_fan_table->usFanGainLiquid; 1017 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainVrVddc 1018 = fiji_fan_table->usFanGainVrVddc; 1019 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainVrMvdd 1020 = fiji_fan_table->usFanGainVrMvdd; 1021 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainPlx 1022 = fiji_fan_table->usFanGainPlx; 1023 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainHbm 1024 = fiji_fan_table->usFanGainHbm; 1025 } 1026 1027 return 0; 1028 } 1029 1030 /** 1031 * Private Function used during initialization. 1032 * Inspect the PowerPlay table for obvious signs of corruption. 1033 * @param hwmgr Pointer to the hardware manager. 1034 * @param powerplay_table Pointer to the PowerPlay Table. 1035 * @exception 2 if the powerplay table is incorrect. 1036 */ 1037 static int check_powerplay_tables( 1038 struct pp_hwmgr *hwmgr, 1039 const ATOM_Tonga_POWERPLAYTABLE *powerplay_table 1040 ) 1041 { 1042 const ATOM_Tonga_State_Array *state_arrays; 1043 1044 state_arrays = (ATOM_Tonga_State_Array *)(((unsigned long)powerplay_table) + 1045 le16_to_cpu(powerplay_table->usStateArrayOffset)); 1046 1047 PP_ASSERT_WITH_CODE((ATOM_Tonga_TABLE_REVISION_TONGA <= 1048 powerplay_table->sHeader.ucTableFormatRevision), 1049 "Unsupported PPTable format!", return -1); 1050 PP_ASSERT_WITH_CODE((0 != powerplay_table->usStateArrayOffset), 1051 "State table is not set!", return -1); 1052 PP_ASSERT_WITH_CODE((0 < powerplay_table->sHeader.usStructureSize), 1053 "Invalid PowerPlay Table!", return -1); 1054 PP_ASSERT_WITH_CODE((0 < state_arrays->ucNumEntries), 1055 "Invalid PowerPlay Table!", return -1); 1056 1057 return 0; 1058 } 1059 1060 static int pp_tables_v1_0_initialize(struct pp_hwmgr *hwmgr) 1061 { 1062 int result = 0; 1063 const ATOM_Tonga_POWERPLAYTABLE *powerplay_table; 1064 1065 hwmgr->pptable = kzalloc(sizeof(struct phm_ppt_v1_information), GFP_KERNEL); 1066 1067 PP_ASSERT_WITH_CODE((NULL != hwmgr->pptable), 1068 "Failed to allocate hwmgr->pptable!", return -ENOMEM); 1069 1070 memset(hwmgr->pptable, 0x00, sizeof(struct phm_ppt_v1_information)); 1071 1072 powerplay_table = get_powerplay_table(hwmgr); 1073 1074 PP_ASSERT_WITH_CODE((NULL != powerplay_table), 1075 "Missing PowerPlay Table!", return -1); 1076 1077 result = check_powerplay_tables(hwmgr, powerplay_table); 1078 1079 PP_ASSERT_WITH_CODE((result == 0), 1080 "check_powerplay_tables failed", return result); 1081 1082 result = set_platform_caps(hwmgr, 1083 le32_to_cpu(powerplay_table->ulPlatformCaps)); 1084 1085 PP_ASSERT_WITH_CODE((result == 0), 1086 "set_platform_caps failed", return result); 1087 1088 result = init_thermal_controller(hwmgr, powerplay_table); 1089 1090 PP_ASSERT_WITH_CODE((result == 0), 1091 "init_thermal_controller failed", return result); 1092 1093 result = init_over_drive_limits(hwmgr, powerplay_table); 1094 1095 PP_ASSERT_WITH_CODE((result == 0), 1096 "init_over_drive_limits failed", return result); 1097 1098 result = init_clock_voltage_dependency(hwmgr, powerplay_table); 1099 1100 PP_ASSERT_WITH_CODE((result == 0), 1101 "init_clock_voltage_dependency failed", return result); 1102 1103 result = init_dpm_2_parameters(hwmgr, powerplay_table); 1104 1105 PP_ASSERT_WITH_CODE((result == 0), 1106 "init_dpm_2_parameters failed", return result); 1107 1108 return result; 1109 } 1110 1111 static int pp_tables_v1_0_uninitialize(struct pp_hwmgr *hwmgr) 1112 { 1113 struct phm_ppt_v1_information *pp_table_information = 1114 (struct phm_ppt_v1_information *)(hwmgr->pptable); 1115 1116 kfree(pp_table_information->vdd_dep_on_sclk); 1117 pp_table_information->vdd_dep_on_sclk = NULL; 1118 1119 kfree(pp_table_information->vdd_dep_on_mclk); 1120 pp_table_information->vdd_dep_on_mclk = NULL; 1121 1122 kfree(pp_table_information->valid_mclk_values); 1123 pp_table_information->valid_mclk_values = NULL; 1124 1125 kfree(pp_table_information->valid_sclk_values); 1126 pp_table_information->valid_sclk_values = NULL; 1127 1128 kfree(pp_table_information->vddc_lookup_table); 1129 pp_table_information->vddc_lookup_table = NULL; 1130 1131 kfree(pp_table_information->vddgfx_lookup_table); 1132 pp_table_information->vddgfx_lookup_table = NULL; 1133 1134 kfree(pp_table_information->mm_dep_table); 1135 pp_table_information->mm_dep_table = NULL; 1136 1137 kfree(pp_table_information->cac_dtp_table); 1138 pp_table_information->cac_dtp_table = NULL; 1139 1140 kfree(hwmgr->dyn_state.cac_dtp_table); 1141 hwmgr->dyn_state.cac_dtp_table = NULL; 1142 1143 kfree(pp_table_information->ppm_parameter_table); 1144 pp_table_information->ppm_parameter_table = NULL; 1145 1146 kfree(pp_table_information->pcie_table); 1147 pp_table_information->pcie_table = NULL; 1148 1149 kfree(pp_table_information->gpio_table); 1150 pp_table_information->gpio_table = NULL; 1151 1152 kfree(hwmgr->pptable); 1153 hwmgr->pptable = NULL; 1154 1155 return 0; 1156 } 1157 1158 const struct pp_table_func pptable_v1_0_funcs = { 1159 .pptable_init = pp_tables_v1_0_initialize, 1160 .pptable_fini = pp_tables_v1_0_uninitialize, 1161 }; 1162 1163 int get_number_of_powerplay_table_entries_v1_0(struct pp_hwmgr *hwmgr) 1164 { 1165 ATOM_Tonga_State_Array const *state_arrays; 1166 const ATOM_Tonga_POWERPLAYTABLE *pp_table = get_powerplay_table(hwmgr); 1167 1168 PP_ASSERT_WITH_CODE((NULL != pp_table), 1169 "Missing PowerPlay Table!", return -1); 1170 PP_ASSERT_WITH_CODE((pp_table->sHeader.ucTableFormatRevision >= 1171 ATOM_Tonga_TABLE_REVISION_TONGA), 1172 "Incorrect PowerPlay table revision!", return -1); 1173 1174 state_arrays = (ATOM_Tonga_State_Array *)(((unsigned long)pp_table) + 1175 le16_to_cpu(pp_table->usStateArrayOffset)); 1176 1177 return (uint32_t)(state_arrays->ucNumEntries); 1178 } 1179 1180 /** 1181 * Private function to convert flags stored in the BIOS to software flags in PowerPlay. 1182 */ 1183 static uint32_t make_classification_flags(struct pp_hwmgr *hwmgr, 1184 uint16_t classification, uint16_t classification2) 1185 { 1186 uint32_t result = 0; 1187 1188 if (classification & ATOM_PPLIB_CLASSIFICATION_BOOT) 1189 result |= PP_StateClassificationFlag_Boot; 1190 1191 if (classification & ATOM_PPLIB_CLASSIFICATION_THERMAL) 1192 result |= PP_StateClassificationFlag_Thermal; 1193 1194 if (classification & ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE) 1195 result |= PP_StateClassificationFlag_LimitedPowerSource; 1196 1197 if (classification & ATOM_PPLIB_CLASSIFICATION_REST) 1198 result |= PP_StateClassificationFlag_Rest; 1199 1200 if (classification & ATOM_PPLIB_CLASSIFICATION_FORCED) 1201 result |= PP_StateClassificationFlag_Forced; 1202 1203 if (classification & ATOM_PPLIB_CLASSIFICATION_ACPI) 1204 result |= PP_StateClassificationFlag_ACPI; 1205 1206 if (classification2 & ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2) 1207 result |= PP_StateClassificationFlag_LimitedPowerSource_2; 1208 1209 return result; 1210 } 1211 1212 static int ppt_get_num_of_vce_state_table_entries_v1_0(struct pp_hwmgr *hwmgr) 1213 { 1214 const ATOM_Tonga_POWERPLAYTABLE *pp_table = get_powerplay_table(hwmgr); 1215 const ATOM_Tonga_VCE_State_Table *vce_state_table; 1216 1217 1218 if (pp_table == NULL) 1219 return 0; 1220 1221 vce_state_table = (void *)pp_table + 1222 le16_to_cpu(pp_table->usVCEStateTableOffset); 1223 1224 return vce_state_table->ucNumEntries; 1225 } 1226 1227 static int ppt_get_vce_state_table_entry_v1_0(struct pp_hwmgr *hwmgr, uint32_t i, 1228 struct amd_vce_state *vce_state, void **clock_info, uint32_t *flag) 1229 { 1230 const ATOM_Tonga_VCE_State_Record *vce_state_record; 1231 ATOM_Tonga_SCLK_Dependency_Record *sclk_dep_record; 1232 ATOM_Tonga_MCLK_Dependency_Record *mclk_dep_record; 1233 ATOM_Tonga_MM_Dependency_Record *mm_dep_record; 1234 const ATOM_Tonga_POWERPLAYTABLE *pptable = get_powerplay_table(hwmgr); 1235 const ATOM_Tonga_VCE_State_Table *vce_state_table = (ATOM_Tonga_VCE_State_Table *)(((unsigned long)pptable) 1236 + le16_to_cpu(pptable->usVCEStateTableOffset)); 1237 const ATOM_Tonga_SCLK_Dependency_Table *sclk_dep_table = (ATOM_Tonga_SCLK_Dependency_Table *)(((unsigned long)pptable) 1238 + le16_to_cpu(pptable->usSclkDependencyTableOffset)); 1239 const ATOM_Tonga_MCLK_Dependency_Table *mclk_dep_table = (ATOM_Tonga_MCLK_Dependency_Table *)(((unsigned long)pptable) 1240 + le16_to_cpu(pptable->usMclkDependencyTableOffset)); 1241 const ATOM_Tonga_MM_Dependency_Table *mm_dep_table = (ATOM_Tonga_MM_Dependency_Table *)(((unsigned long)pptable) 1242 + le16_to_cpu(pptable->usMMDependencyTableOffset)); 1243 1244 PP_ASSERT_WITH_CODE((i < vce_state_table->ucNumEntries), 1245 "Requested state entry ID is out of range!", 1246 return -EINVAL); 1247 1248 vce_state_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( 1249 ATOM_Tonga_VCE_State_Record, 1250 entries, vce_state_table, i); 1251 sclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( 1252 ATOM_Tonga_SCLK_Dependency_Record, 1253 entries, sclk_dep_table, 1254 vce_state_record->ucSCLKIndex); 1255 mm_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( 1256 ATOM_Tonga_MM_Dependency_Record, 1257 entries, mm_dep_table, 1258 vce_state_record->ucVCEClockIndex); 1259 *flag = vce_state_record->ucFlag; 1260 1261 vce_state->evclk = mm_dep_record->ulEClk; 1262 vce_state->ecclk = mm_dep_record->ulEClk; 1263 vce_state->sclk = sclk_dep_record->ulSclk; 1264 1265 if (vce_state_record->ucMCLKIndex >= mclk_dep_table->ucNumEntries) 1266 mclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( 1267 ATOM_Tonga_MCLK_Dependency_Record, 1268 entries, mclk_dep_table, 1269 mclk_dep_table->ucNumEntries - 1); 1270 else 1271 mclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( 1272 ATOM_Tonga_MCLK_Dependency_Record, 1273 entries, mclk_dep_table, 1274 vce_state_record->ucMCLKIndex); 1275 1276 vce_state->mclk = mclk_dep_record->ulMclk; 1277 return 0; 1278 } 1279 1280 /** 1281 * Create a Power State out of an entry in the PowerPlay table. 1282 * This function is called by the hardware back-end. 1283 * @param hwmgr Pointer to the hardware manager. 1284 * @param entry_index The index of the entry to be extracted from the table. 1285 * @param power_state The address of the PowerState instance being created. 1286 * @return -1 if the entry cannot be retrieved. 1287 */ 1288 int get_powerplay_table_entry_v1_0(struct pp_hwmgr *hwmgr, 1289 uint32_t entry_index, struct pp_power_state *power_state, 1290 int (*call_back_func)(struct pp_hwmgr *, void *, 1291 struct pp_power_state *, void *, uint32_t)) 1292 { 1293 int result = 0; 1294 const ATOM_Tonga_State_Array *state_arrays; 1295 const ATOM_Tonga_State *state_entry; 1296 const ATOM_Tonga_POWERPLAYTABLE *pp_table = get_powerplay_table(hwmgr); 1297 int i, j; 1298 uint32_t flags = 0; 1299 1300 PP_ASSERT_WITH_CODE((NULL != pp_table), "Missing PowerPlay Table!", return -1;); 1301 power_state->classification.bios_index = entry_index; 1302 1303 if (pp_table->sHeader.ucTableFormatRevision >= 1304 ATOM_Tonga_TABLE_REVISION_TONGA) { 1305 state_arrays = (ATOM_Tonga_State_Array *)(((unsigned long)pp_table) + 1306 le16_to_cpu(pp_table->usStateArrayOffset)); 1307 1308 PP_ASSERT_WITH_CODE((0 < pp_table->usStateArrayOffset), 1309 "Invalid PowerPlay Table State Array Offset.", return -1); 1310 PP_ASSERT_WITH_CODE((0 < state_arrays->ucNumEntries), 1311 "Invalid PowerPlay Table State Array.", return -1); 1312 PP_ASSERT_WITH_CODE((entry_index <= state_arrays->ucNumEntries), 1313 "Invalid PowerPlay Table State Array Entry.", return -1); 1314 1315 state_entry = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( 1316 ATOM_Tonga_State, entries, 1317 state_arrays, entry_index); 1318 1319 result = call_back_func(hwmgr, (void *)state_entry, power_state, 1320 (void *)pp_table, 1321 make_classification_flags(hwmgr, 1322 le16_to_cpu(state_entry->usClassification), 1323 le16_to_cpu(state_entry->usClassification2))); 1324 } 1325 1326 if (!result && (power_state->classification.flags & 1327 PP_StateClassificationFlag_Boot)) 1328 result = hwmgr->hwmgr_func->patch_boot_state(hwmgr, &(power_state->hardware)); 1329 1330 hwmgr->num_vce_state_tables = i = ppt_get_num_of_vce_state_table_entries_v1_0(hwmgr); 1331 1332 if ((i != 0) && (i <= AMD_MAX_VCE_LEVELS)) { 1333 for (j = 0; j < i; j++) 1334 ppt_get_vce_state_table_entry_v1_0(hwmgr, j, &(hwmgr->vce_states[j]), NULL, &flags); 1335 } 1336 1337 return result; 1338 } 1339 1340