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