0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023 #include "pp_debug.h"
0024 #include <linux/module.h>
0025 #include <linux/slab.h>
0026
0027 #include "process_pptables_v1_0.h"
0028 #include "ppatomctrl.h"
0029 #include "atombios.h"
0030 #include "hwmgr.h"
0031 #include "cgs_common.h"
0032 #include "pptable_v1_0.h"
0033
0034
0035
0036
0037
0038
0039
0040 static void set_hw_cap(struct pp_hwmgr *hwmgr, bool setIt, enum phm_platform_caps cap)
0041 {
0042 if (setIt)
0043 phm_cap_set(hwmgr->platform_descriptor.platformCaps, cap);
0044 else
0045 phm_cap_unset(hwmgr->platform_descriptor.platformCaps, cap);
0046 }
0047
0048
0049
0050
0051
0052
0053
0054
0055 static int set_platform_caps(struct pp_hwmgr *hwmgr, uint32_t powerplay_caps)
0056 {
0057 PP_ASSERT_WITH_CODE((~powerplay_caps & ____RETIRE16____),
0058 "ATOM_PP_PLATFORM_CAP_ASPM_L1 is not supported!", continue);
0059 PP_ASSERT_WITH_CODE((~powerplay_caps & ____RETIRE64____),
0060 "ATOM_PP_PLATFORM_CAP_GEMINIPRIMARY is not supported!", continue);
0061 PP_ASSERT_WITH_CODE((~powerplay_caps & ____RETIRE512____),
0062 "ATOM_PP_PLATFORM_CAP_SIDEPORTCONTROL is not supported!", continue);
0063 PP_ASSERT_WITH_CODE((~powerplay_caps & ____RETIRE1024____),
0064 "ATOM_PP_PLATFORM_CAP_TURNOFFPLL_ASPML1 is not supported!", continue);
0065 PP_ASSERT_WITH_CODE((~powerplay_caps & ____RETIRE2048____),
0066 "ATOM_PP_PLATFORM_CAP_HTLINKCONTROL is not supported!", continue);
0067
0068 set_hw_cap(
0069 hwmgr,
0070 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_POWERPLAY),
0071 PHM_PlatformCaps_PowerPlaySupport
0072 );
0073
0074 set_hw_cap(
0075 hwmgr,
0076 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_SBIOSPOWERSOURCE),
0077 PHM_PlatformCaps_BiosPowerSourceControl
0078 );
0079
0080 set_hw_cap(
0081 hwmgr,
0082 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_HARDWAREDC),
0083 PHM_PlatformCaps_AutomaticDCTransition
0084 );
0085
0086 set_hw_cap(
0087 hwmgr,
0088 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_MVDD_CONTROL),
0089 PHM_PlatformCaps_EnableMVDDControl
0090 );
0091
0092 set_hw_cap(
0093 hwmgr,
0094 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_VDDCI_CONTROL),
0095 PHM_PlatformCaps_ControlVDDCI
0096 );
0097
0098 set_hw_cap(
0099 hwmgr,
0100 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_VDDGFX_CONTROL),
0101 PHM_PlatformCaps_ControlVDDGFX
0102 );
0103
0104 set_hw_cap(
0105 hwmgr,
0106 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_BACO),
0107 PHM_PlatformCaps_BACO
0108 );
0109
0110 set_hw_cap(
0111 hwmgr,
0112 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_DISABLE_VOLTAGE_ISLAND),
0113 PHM_PlatformCaps_DisableVoltageIsland
0114 );
0115
0116 set_hw_cap(
0117 hwmgr,
0118 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_COMBINE_PCC_WITH_THERMAL_SIGNAL),
0119 PHM_PlatformCaps_CombinePCCWithThermalSignal
0120 );
0121
0122 set_hw_cap(
0123 hwmgr,
0124 0 != (powerplay_caps & ATOM_TONGA_PLATFORM_LOAD_POST_PRODUCTION_FIRMWARE),
0125 PHM_PlatformCaps_LoadPostProductionFirmware
0126 );
0127
0128 return 0;
0129 }
0130
0131
0132
0133
0134 static const void *get_powerplay_table(struct pp_hwmgr *hwmgr)
0135 {
0136 int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
0137
0138 u16 size;
0139 u8 frev, crev;
0140 void *table_address = (void *)hwmgr->soft_pp_table;
0141
0142 if (!table_address) {
0143 table_address = (ATOM_Tonga_POWERPLAYTABLE *)
0144 smu_atom_get_data_table(hwmgr->adev,
0145 index, &size, &frev, &crev);
0146 hwmgr->soft_pp_table = table_address;
0147 hwmgr->soft_pp_table_size = size;
0148 }
0149
0150 return table_address;
0151 }
0152
0153 static int get_vddc_lookup_table(
0154 struct pp_hwmgr *hwmgr,
0155 phm_ppt_v1_voltage_lookup_table **lookup_table,
0156 const ATOM_Tonga_Voltage_Lookup_Table *vddc_lookup_pp_tables,
0157 uint32_t max_levels
0158 )
0159 {
0160 uint32_t i;
0161 phm_ppt_v1_voltage_lookup_table *table;
0162 phm_ppt_v1_voltage_lookup_record *record;
0163 ATOM_Tonga_Voltage_Lookup_Record *atom_record;
0164
0165 PP_ASSERT_WITH_CODE((0 != vddc_lookup_pp_tables->ucNumEntries),
0166 "Invalid CAC Leakage PowerPlay Table!", return 1);
0167
0168 table = kzalloc(struct_size(table, entries, max_levels), GFP_KERNEL);
0169 if (!table)
0170 return -ENOMEM;
0171
0172 table->count = vddc_lookup_pp_tables->ucNumEntries;
0173
0174 for (i = 0; i < vddc_lookup_pp_tables->ucNumEntries; i++) {
0175 record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
0176 phm_ppt_v1_voltage_lookup_record,
0177 entries, table, i);
0178 atom_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
0179 ATOM_Tonga_Voltage_Lookup_Record,
0180 entries, vddc_lookup_pp_tables, i);
0181 record->us_calculated = 0;
0182 record->us_vdd = le16_to_cpu(atom_record->usVdd);
0183 record->us_cac_low = le16_to_cpu(atom_record->usCACLow);
0184 record->us_cac_mid = le16_to_cpu(atom_record->usCACMid);
0185 record->us_cac_high = le16_to_cpu(atom_record->usCACHigh);
0186 }
0187
0188 *lookup_table = table;
0189
0190 return 0;
0191 }
0192
0193
0194
0195
0196
0197
0198
0199 static int get_platform_power_management_table(
0200 struct pp_hwmgr *hwmgr,
0201 ATOM_Tonga_PPM_Table *atom_ppm_table)
0202 {
0203 struct phm_ppm_table *ptr = kzalloc(sizeof(ATOM_Tonga_PPM_Table), GFP_KERNEL);
0204 struct phm_ppt_v1_information *pp_table_information =
0205 (struct phm_ppt_v1_information *)(hwmgr->pptable);
0206
0207 if (NULL == ptr)
0208 return -ENOMEM;
0209
0210 ptr->ppm_design
0211 = atom_ppm_table->ucPpmDesign;
0212 ptr->cpu_core_number
0213 = le16_to_cpu(atom_ppm_table->usCpuCoreNumber);
0214 ptr->platform_tdp
0215 = le32_to_cpu(atom_ppm_table->ulPlatformTDP);
0216 ptr->small_ac_platform_tdp
0217 = le32_to_cpu(atom_ppm_table->ulSmallACPlatformTDP);
0218 ptr->platform_tdc
0219 = le32_to_cpu(atom_ppm_table->ulPlatformTDC);
0220 ptr->small_ac_platform_tdc
0221 = le32_to_cpu(atom_ppm_table->ulSmallACPlatformTDC);
0222 ptr->apu_tdp
0223 = le32_to_cpu(atom_ppm_table->ulApuTDP);
0224 ptr->dgpu_tdp
0225 = le32_to_cpu(atom_ppm_table->ulDGpuTDP);
0226 ptr->dgpu_ulv_power
0227 = le32_to_cpu(atom_ppm_table->ulDGpuUlvPower);
0228 ptr->tj_max
0229 = le32_to_cpu(atom_ppm_table->ulTjmax);
0230
0231 pp_table_information->ppm_parameter_table = ptr;
0232
0233 return 0;
0234 }
0235
0236
0237
0238
0239
0240
0241
0242 static int init_dpm_2_parameters(
0243 struct pp_hwmgr *hwmgr,
0244 const ATOM_Tonga_POWERPLAYTABLE *powerplay_table
0245 )
0246 {
0247 int result = 0;
0248 struct phm_ppt_v1_information *pp_table_information = (struct phm_ppt_v1_information *)(hwmgr->pptable);
0249 ATOM_Tonga_PPM_Table *atom_ppm_table;
0250 uint32_t disable_ppm = 0;
0251 uint32_t disable_power_control = 0;
0252
0253 pp_table_information->us_ulv_voltage_offset =
0254 le16_to_cpu(powerplay_table->usUlvVoltageOffset);
0255
0256 pp_table_information->ppm_parameter_table = NULL;
0257 pp_table_information->vddc_lookup_table = NULL;
0258 pp_table_information->vddgfx_lookup_table = NULL;
0259
0260 hwmgr->platform_descriptor.TDPODLimit =
0261 le16_to_cpu(powerplay_table->usPowerControlLimit);
0262 hwmgr->platform_descriptor.TDPAdjustment = 0;
0263 hwmgr->platform_descriptor.VidAdjustment = 0;
0264 hwmgr->platform_descriptor.VidAdjustmentPolarity = 0;
0265 hwmgr->platform_descriptor.VidMinLimit = 0;
0266 hwmgr->platform_descriptor.VidMaxLimit = 1500000;
0267 hwmgr->platform_descriptor.VidStep = 6250;
0268
0269 disable_power_control = 0;
0270 if (0 == disable_power_control) {
0271
0272 if (hwmgr->platform_descriptor.TDPODLimit != 0)
0273 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
0274 PHM_PlatformCaps_PowerControl);
0275 }
0276
0277 if (0 != powerplay_table->usVddcLookupTableOffset) {
0278 const ATOM_Tonga_Voltage_Lookup_Table *pVddcCACTable =
0279 (ATOM_Tonga_Voltage_Lookup_Table *)(((unsigned long)powerplay_table) +
0280 le16_to_cpu(powerplay_table->usVddcLookupTableOffset));
0281
0282 result = get_vddc_lookup_table(hwmgr,
0283 &pp_table_information->vddc_lookup_table, pVddcCACTable, 16);
0284 }
0285
0286 if (0 != powerplay_table->usVddgfxLookupTableOffset) {
0287 const ATOM_Tonga_Voltage_Lookup_Table *pVddgfxCACTable =
0288 (ATOM_Tonga_Voltage_Lookup_Table *)(((unsigned long)powerplay_table) +
0289 le16_to_cpu(powerplay_table->usVddgfxLookupTableOffset));
0290
0291 result = get_vddc_lookup_table(hwmgr,
0292 &pp_table_information->vddgfx_lookup_table, pVddgfxCACTable, 16);
0293 }
0294
0295 disable_ppm = 0;
0296 if (0 == disable_ppm) {
0297 atom_ppm_table = (ATOM_Tonga_PPM_Table *)
0298 (((unsigned long)powerplay_table) + le16_to_cpu(powerplay_table->usPPMTableOffset));
0299
0300 if (0 != powerplay_table->usPPMTableOffset) {
0301 if (get_platform_power_management_table(hwmgr, atom_ppm_table) == 0) {
0302 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
0303 PHM_PlatformCaps_EnablePlatformPowerManagement);
0304 }
0305 }
0306 }
0307
0308 return result;
0309 }
0310
0311 static int get_valid_clk(
0312 struct pp_hwmgr *hwmgr,
0313 struct phm_clock_array **clk_table,
0314 phm_ppt_v1_clock_voltage_dependency_table const *clk_volt_pp_table
0315 )
0316 {
0317 uint32_t i;
0318 struct phm_clock_array *table;
0319 phm_ppt_v1_clock_voltage_dependency_record *dep_record;
0320
0321 PP_ASSERT_WITH_CODE((0 != clk_volt_pp_table->count),
0322 "Invalid PowerPlay Table!", return -1);
0323
0324 table = kzalloc(struct_size(table, values, clk_volt_pp_table->count),
0325 GFP_KERNEL);
0326 if (!table)
0327 return -ENOMEM;
0328
0329 table->count = (uint32_t)clk_volt_pp_table->count;
0330
0331 for (i = 0; i < table->count; i++) {
0332 dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
0333 phm_ppt_v1_clock_voltage_dependency_record,
0334 entries, clk_volt_pp_table, i);
0335 table->values[i] = (uint32_t)dep_record->clk;
0336 }
0337 *clk_table = table;
0338
0339 return 0;
0340 }
0341
0342 static int get_hard_limits(
0343 struct pp_hwmgr *hwmgr,
0344 struct phm_clock_and_voltage_limits *limits,
0345 ATOM_Tonga_Hard_Limit_Table const *limitable
0346 )
0347 {
0348 PP_ASSERT_WITH_CODE((0 != limitable->ucNumEntries), "Invalid PowerPlay Table!", return -1);
0349
0350
0351 limits->sclk = le32_to_cpu(limitable->entries[0].ulSCLKLimit);
0352 limits->mclk = le32_to_cpu(limitable->entries[0].ulMCLKLimit);
0353 limits->vddc = le16_to_cpu(limitable->entries[0].usVddcLimit);
0354 limits->vddci = le16_to_cpu(limitable->entries[0].usVddciLimit);
0355 limits->vddgfx = le16_to_cpu(limitable->entries[0].usVddgfxLimit);
0356
0357 return 0;
0358 }
0359
0360 static int get_mclk_voltage_dependency_table(
0361 struct pp_hwmgr *hwmgr,
0362 phm_ppt_v1_clock_voltage_dependency_table **pp_tonga_mclk_dep_table,
0363 ATOM_Tonga_MCLK_Dependency_Table const *mclk_dep_table
0364 )
0365 {
0366 uint32_t i;
0367 phm_ppt_v1_clock_voltage_dependency_table *mclk_table;
0368 phm_ppt_v1_clock_voltage_dependency_record *mclk_table_record;
0369 ATOM_Tonga_MCLK_Dependency_Record *mclk_dep_record;
0370
0371 PP_ASSERT_WITH_CODE((0 != mclk_dep_table->ucNumEntries),
0372 "Invalid PowerPlay Table!", return -1);
0373
0374 mclk_table = kzalloc(struct_size(mclk_table, entries, mclk_dep_table->ucNumEntries),
0375 GFP_KERNEL);
0376 if (!mclk_table)
0377 return -ENOMEM;
0378
0379 mclk_table->count = (uint32_t)mclk_dep_table->ucNumEntries;
0380
0381 for (i = 0; i < mclk_dep_table->ucNumEntries; i++) {
0382 mclk_table_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
0383 phm_ppt_v1_clock_voltage_dependency_record,
0384 entries, mclk_table, i);
0385 mclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
0386 ATOM_Tonga_MCLK_Dependency_Record,
0387 entries, mclk_dep_table, i);
0388 mclk_table_record->vddInd = mclk_dep_record->ucVddcInd;
0389 mclk_table_record->vdd_offset = le16_to_cpu(mclk_dep_record->usVddgfxOffset);
0390 mclk_table_record->vddci = le16_to_cpu(mclk_dep_record->usVddci);
0391 mclk_table_record->mvdd = le16_to_cpu(mclk_dep_record->usMvdd);
0392 mclk_table_record->clk = le32_to_cpu(mclk_dep_record->ulMclk);
0393 }
0394
0395 *pp_tonga_mclk_dep_table = mclk_table;
0396
0397 return 0;
0398 }
0399
0400 static int get_sclk_voltage_dependency_table(
0401 struct pp_hwmgr *hwmgr,
0402 phm_ppt_v1_clock_voltage_dependency_table **pp_tonga_sclk_dep_table,
0403 PPTable_Generic_SubTable_Header const *sclk_dep_table
0404 )
0405 {
0406 uint32_t i;
0407 phm_ppt_v1_clock_voltage_dependency_table *sclk_table;
0408 phm_ppt_v1_clock_voltage_dependency_record *sclk_table_record;
0409
0410 if (sclk_dep_table->ucRevId < 1) {
0411 const ATOM_Tonga_SCLK_Dependency_Table *tonga_table =
0412 (ATOM_Tonga_SCLK_Dependency_Table *)sclk_dep_table;
0413 ATOM_Tonga_SCLK_Dependency_Record *sclk_dep_record;
0414
0415 PP_ASSERT_WITH_CODE((0 != tonga_table->ucNumEntries),
0416 "Invalid PowerPlay Table!", return -1);
0417
0418 sclk_table = kzalloc(struct_size(sclk_table, entries, tonga_table->ucNumEntries),
0419 GFP_KERNEL);
0420 if (!sclk_table)
0421 return -ENOMEM;
0422
0423 sclk_table->count = (uint32_t)tonga_table->ucNumEntries;
0424
0425 for (i = 0; i < tonga_table->ucNumEntries; i++) {
0426 sclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
0427 ATOM_Tonga_SCLK_Dependency_Record,
0428 entries, tonga_table, i);
0429 sclk_table_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
0430 phm_ppt_v1_clock_voltage_dependency_record,
0431 entries, sclk_table, i);
0432 sclk_table_record->vddInd = sclk_dep_record->ucVddInd;
0433 sclk_table_record->vdd_offset = le16_to_cpu(sclk_dep_record->usVddcOffset);
0434 sclk_table_record->clk = le32_to_cpu(sclk_dep_record->ulSclk);
0435 sclk_table_record->cks_enable =
0436 (((sclk_dep_record->ucCKSVOffsetandDisable & 0x80) >> 7) == 0) ? 1 : 0;
0437 sclk_table_record->cks_voffset = (sclk_dep_record->ucCKSVOffsetandDisable & 0x7F);
0438 }
0439 } else {
0440 const ATOM_Polaris_SCLK_Dependency_Table *polaris_table =
0441 (ATOM_Polaris_SCLK_Dependency_Table *)sclk_dep_table;
0442 ATOM_Polaris_SCLK_Dependency_Record *sclk_dep_record;
0443
0444 PP_ASSERT_WITH_CODE((0 != polaris_table->ucNumEntries),
0445 "Invalid PowerPlay Table!", return -1);
0446
0447 sclk_table = kzalloc(struct_size(sclk_table, entries, polaris_table->ucNumEntries),
0448 GFP_KERNEL);
0449 if (!sclk_table)
0450 return -ENOMEM;
0451
0452 sclk_table->count = (uint32_t)polaris_table->ucNumEntries;
0453
0454 for (i = 0; i < polaris_table->ucNumEntries; i++) {
0455 sclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
0456 ATOM_Polaris_SCLK_Dependency_Record,
0457 entries, polaris_table, i);
0458 sclk_table_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
0459 phm_ppt_v1_clock_voltage_dependency_record,
0460 entries, sclk_table, i);
0461 sclk_table_record->vddInd = sclk_dep_record->ucVddInd;
0462 sclk_table_record->vdd_offset = le16_to_cpu(sclk_dep_record->usVddcOffset);
0463 sclk_table_record->clk = le32_to_cpu(sclk_dep_record->ulSclk);
0464 sclk_table_record->cks_enable =
0465 (((sclk_dep_record->ucCKSVOffsetandDisable & 0x80) >> 7) == 0) ? 1 : 0;
0466 sclk_table_record->cks_voffset = (sclk_dep_record->ucCKSVOffsetandDisable & 0x7F);
0467 sclk_table_record->sclk_offset = le32_to_cpu(sclk_dep_record->ulSclkOffset);
0468 }
0469 }
0470 *pp_tonga_sclk_dep_table = sclk_table;
0471
0472 return 0;
0473 }
0474
0475 static int get_pcie_table(
0476 struct pp_hwmgr *hwmgr,
0477 phm_ppt_v1_pcie_table **pp_tonga_pcie_table,
0478 PPTable_Generic_SubTable_Header const *ptable
0479 )
0480 {
0481 uint32_t i, pcie_count;
0482 phm_ppt_v1_pcie_table *pcie_table;
0483 struct phm_ppt_v1_information *pp_table_information =
0484 (struct phm_ppt_v1_information *)(hwmgr->pptable);
0485 phm_ppt_v1_pcie_record *pcie_record;
0486
0487 if (ptable->ucRevId < 1) {
0488 const ATOM_Tonga_PCIE_Table *atom_pcie_table = (ATOM_Tonga_PCIE_Table *)ptable;
0489 ATOM_Tonga_PCIE_Record *atom_pcie_record;
0490
0491 PP_ASSERT_WITH_CODE((atom_pcie_table->ucNumEntries != 0),
0492 "Invalid PowerPlay Table!", return -1);
0493
0494 pcie_table = kzalloc(struct_size(pcie_table, entries,
0495 atom_pcie_table->ucNumEntries),
0496 GFP_KERNEL);
0497 if (!pcie_table)
0498 return -ENOMEM;
0499
0500
0501
0502
0503
0504 pcie_count = (pp_table_information->vdd_dep_on_sclk->count) + 1;
0505 if ((uint32_t)atom_pcie_table->ucNumEntries <= pcie_count)
0506 pcie_count = (uint32_t)atom_pcie_table->ucNumEntries;
0507 else
0508 pr_err("Number of Pcie Entries exceed the number of SCLK Dpm Levels! Disregarding the excess entries...\n");
0509
0510 pcie_table->count = pcie_count;
0511 for (i = 0; i < pcie_count; i++) {
0512 pcie_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
0513 phm_ppt_v1_pcie_record,
0514 entries, pcie_table, i);
0515 atom_pcie_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
0516 ATOM_Tonga_PCIE_Record,
0517 entries, atom_pcie_table, i);
0518 pcie_record->gen_speed = atom_pcie_record->ucPCIEGenSpeed;
0519 pcie_record->lane_width = le16_to_cpu(atom_pcie_record->usPCIELaneWidth);
0520 }
0521
0522 *pp_tonga_pcie_table = pcie_table;
0523 } else {
0524
0525 const ATOM_Polaris10_PCIE_Table *atom_pcie_table = (ATOM_Polaris10_PCIE_Table *)ptable;
0526 ATOM_Polaris10_PCIE_Record *atom_pcie_record;
0527
0528 PP_ASSERT_WITH_CODE((atom_pcie_table->ucNumEntries != 0),
0529 "Invalid PowerPlay Table!", return -1);
0530
0531 pcie_table = kzalloc(struct_size(pcie_table, entries,
0532 atom_pcie_table->ucNumEntries),
0533 GFP_KERNEL);
0534 if (!pcie_table)
0535 return -ENOMEM;
0536
0537
0538
0539
0540
0541 pcie_count = (pp_table_information->vdd_dep_on_sclk->count) + 1;
0542 if ((uint32_t)atom_pcie_table->ucNumEntries <= pcie_count)
0543 pcie_count = (uint32_t)atom_pcie_table->ucNumEntries;
0544 else
0545 pr_err("Number of Pcie Entries exceed the number of SCLK Dpm Levels! Disregarding the excess entries...\n");
0546
0547 pcie_table->count = pcie_count;
0548
0549 for (i = 0; i < pcie_count; i++) {
0550 pcie_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
0551 phm_ppt_v1_pcie_record,
0552 entries, pcie_table, i);
0553 atom_pcie_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
0554 ATOM_Polaris10_PCIE_Record,
0555 entries, atom_pcie_table, i);
0556 pcie_record->gen_speed = atom_pcie_record->ucPCIEGenSpeed;
0557 pcie_record->lane_width = le16_to_cpu(atom_pcie_record->usPCIELaneWidth);
0558 pcie_record->pcie_sclk = le32_to_cpu(atom_pcie_record->ulPCIE_Sclk);
0559 }
0560
0561 *pp_tonga_pcie_table = pcie_table;
0562 }
0563
0564 return 0;
0565 }
0566
0567 static int get_cac_tdp_table(
0568 struct pp_hwmgr *hwmgr,
0569 struct phm_cac_tdp_table **cac_tdp_table,
0570 const PPTable_Generic_SubTable_Header * table
0571 )
0572 {
0573 uint32_t table_size;
0574 struct phm_cac_tdp_table *tdp_table;
0575
0576 table_size = sizeof(uint32_t) + sizeof(struct phm_cac_tdp_table);
0577 tdp_table = kzalloc(table_size, GFP_KERNEL);
0578
0579 if (NULL == tdp_table)
0580 return -ENOMEM;
0581
0582 hwmgr->dyn_state.cac_dtp_table = kzalloc(table_size, GFP_KERNEL);
0583
0584 if (NULL == hwmgr->dyn_state.cac_dtp_table) {
0585 kfree(tdp_table);
0586 return -ENOMEM;
0587 }
0588
0589 if (table->ucRevId < 3) {
0590 const ATOM_Tonga_PowerTune_Table *tonga_table =
0591 (ATOM_Tonga_PowerTune_Table *)table;
0592 tdp_table->usTDP = le16_to_cpu(tonga_table->usTDP);
0593 tdp_table->usConfigurableTDP =
0594 le16_to_cpu(tonga_table->usConfigurableTDP);
0595 tdp_table->usTDC = le16_to_cpu(tonga_table->usTDC);
0596 tdp_table->usBatteryPowerLimit =
0597 le16_to_cpu(tonga_table->usBatteryPowerLimit);
0598 tdp_table->usSmallPowerLimit =
0599 le16_to_cpu(tonga_table->usSmallPowerLimit);
0600 tdp_table->usLowCACLeakage =
0601 le16_to_cpu(tonga_table->usLowCACLeakage);
0602 tdp_table->usHighCACLeakage =
0603 le16_to_cpu(tonga_table->usHighCACLeakage);
0604 tdp_table->usMaximumPowerDeliveryLimit =
0605 le16_to_cpu(tonga_table->usMaximumPowerDeliveryLimit);
0606 tdp_table->usDefaultTargetOperatingTemp =
0607 le16_to_cpu(tonga_table->usTjMax);
0608 tdp_table->usTargetOperatingTemp =
0609 le16_to_cpu(tonga_table->usTjMax);
0610 tdp_table->usPowerTuneDataSetID =
0611 le16_to_cpu(tonga_table->usPowerTuneDataSetID);
0612 tdp_table->usSoftwareShutdownTemp =
0613 le16_to_cpu(tonga_table->usSoftwareShutdownTemp);
0614 tdp_table->usClockStretchAmount =
0615 le16_to_cpu(tonga_table->usClockStretchAmount);
0616 } else if (table->ucRevId < 4) {
0617 const ATOM_Fiji_PowerTune_Table *fijitable =
0618 (ATOM_Fiji_PowerTune_Table *)table;
0619 tdp_table->usTDP = le16_to_cpu(fijitable->usTDP);
0620 tdp_table->usConfigurableTDP = le16_to_cpu(fijitable->usConfigurableTDP);
0621 tdp_table->usTDC = le16_to_cpu(fijitable->usTDC);
0622 tdp_table->usBatteryPowerLimit = le16_to_cpu(fijitable->usBatteryPowerLimit);
0623 tdp_table->usSmallPowerLimit = le16_to_cpu(fijitable->usSmallPowerLimit);
0624 tdp_table->usLowCACLeakage = le16_to_cpu(fijitable->usLowCACLeakage);
0625 tdp_table->usHighCACLeakage = le16_to_cpu(fijitable->usHighCACLeakage);
0626 tdp_table->usMaximumPowerDeliveryLimit =
0627 le16_to_cpu(fijitable->usMaximumPowerDeliveryLimit);
0628 tdp_table->usDefaultTargetOperatingTemp =
0629 le16_to_cpu(fijitable->usTjMax);
0630 tdp_table->usTargetOperatingTemp =
0631 le16_to_cpu(fijitable->usTjMax);
0632 tdp_table->usPowerTuneDataSetID =
0633 le16_to_cpu(fijitable->usPowerTuneDataSetID);
0634 tdp_table->usSoftwareShutdownTemp =
0635 le16_to_cpu(fijitable->usSoftwareShutdownTemp);
0636 tdp_table->usClockStretchAmount =
0637 le16_to_cpu(fijitable->usClockStretchAmount);
0638 tdp_table->usTemperatureLimitHotspot =
0639 le16_to_cpu(fijitable->usTemperatureLimitHotspot);
0640 tdp_table->usTemperatureLimitLiquid1 =
0641 le16_to_cpu(fijitable->usTemperatureLimitLiquid1);
0642 tdp_table->usTemperatureLimitLiquid2 =
0643 le16_to_cpu(fijitable->usTemperatureLimitLiquid2);
0644 tdp_table->usTemperatureLimitVrVddc =
0645 le16_to_cpu(fijitable->usTemperatureLimitVrVddc);
0646 tdp_table->usTemperatureLimitVrMvdd =
0647 le16_to_cpu(fijitable->usTemperatureLimitVrMvdd);
0648 tdp_table->usTemperatureLimitPlx =
0649 le16_to_cpu(fijitable->usTemperatureLimitPlx);
0650 tdp_table->ucLiquid1_I2C_address =
0651 fijitable->ucLiquid1_I2C_address;
0652 tdp_table->ucLiquid2_I2C_address =
0653 fijitable->ucLiquid2_I2C_address;
0654 tdp_table->ucLiquid_I2C_Line =
0655 fijitable->ucLiquid_I2C_Line;
0656 tdp_table->ucVr_I2C_address = fijitable->ucVr_I2C_address;
0657 tdp_table->ucVr_I2C_Line = fijitable->ucVr_I2C_Line;
0658 tdp_table->ucPlx_I2C_address = fijitable->ucPlx_I2C_address;
0659 tdp_table->ucPlx_I2C_Line = fijitable->ucPlx_I2C_Line;
0660 } else {
0661 const ATOM_Polaris_PowerTune_Table *polaristable =
0662 (ATOM_Polaris_PowerTune_Table *)table;
0663 tdp_table->usTDP = le16_to_cpu(polaristable->usTDP);
0664 tdp_table->usConfigurableTDP = le16_to_cpu(polaristable->usConfigurableTDP);
0665 tdp_table->usTDC = le16_to_cpu(polaristable->usTDC);
0666 tdp_table->usBatteryPowerLimit = le16_to_cpu(polaristable->usBatteryPowerLimit);
0667 tdp_table->usSmallPowerLimit = le16_to_cpu(polaristable->usSmallPowerLimit);
0668 tdp_table->usLowCACLeakage = le16_to_cpu(polaristable->usLowCACLeakage);
0669 tdp_table->usHighCACLeakage = le16_to_cpu(polaristable->usHighCACLeakage);
0670 tdp_table->usMaximumPowerDeliveryLimit =
0671 le16_to_cpu(polaristable->usMaximumPowerDeliveryLimit);
0672 tdp_table->usDefaultTargetOperatingTemp =
0673 le16_to_cpu(polaristable->usTjMax);
0674 tdp_table->usTargetOperatingTemp =
0675 le16_to_cpu(polaristable->usTjMax);
0676 tdp_table->usPowerTuneDataSetID =
0677 le16_to_cpu(polaristable->usPowerTuneDataSetID);
0678 tdp_table->usSoftwareShutdownTemp =
0679 le16_to_cpu(polaristable->usSoftwareShutdownTemp);
0680 tdp_table->usClockStretchAmount =
0681 le16_to_cpu(polaristable->usClockStretchAmount);
0682 tdp_table->usTemperatureLimitHotspot =
0683 le16_to_cpu(polaristable->usTemperatureLimitHotspot);
0684 tdp_table->usTemperatureLimitLiquid1 =
0685 le16_to_cpu(polaristable->usTemperatureLimitLiquid1);
0686 tdp_table->usTemperatureLimitLiquid2 =
0687 le16_to_cpu(polaristable->usTemperatureLimitLiquid2);
0688 tdp_table->usTemperatureLimitVrVddc =
0689 le16_to_cpu(polaristable->usTemperatureLimitVrVddc);
0690 tdp_table->usTemperatureLimitVrMvdd =
0691 le16_to_cpu(polaristable->usTemperatureLimitVrMvdd);
0692 tdp_table->usTemperatureLimitPlx =
0693 le16_to_cpu(polaristable->usTemperatureLimitPlx);
0694 tdp_table->ucLiquid1_I2C_address =
0695 polaristable->ucLiquid1_I2C_address;
0696 tdp_table->ucLiquid2_I2C_address =
0697 polaristable->ucLiquid2_I2C_address;
0698 tdp_table->ucLiquid_I2C_Line =
0699 polaristable->ucLiquid_I2C_Line;
0700 tdp_table->ucVr_I2C_address = polaristable->ucVr_I2C_address;
0701 tdp_table->ucVr_I2C_Line = polaristable->ucVr_I2C_Line;
0702 tdp_table->ucPlx_I2C_address = polaristable->ucPlx_I2C_address;
0703 tdp_table->ucPlx_I2C_Line = polaristable->ucPlx_I2C_Line;
0704 tdp_table->usBoostPowerLimit = polaristable->usBoostPowerLimit;
0705 tdp_table->ucCKS_LDO_REFSEL = polaristable->ucCKS_LDO_REFSEL;
0706 tdp_table->ucHotSpotOnly = polaristable->ucHotSpotOnly;
0707 }
0708
0709 *cac_tdp_table = tdp_table;
0710
0711 return 0;
0712 }
0713
0714 static int get_mm_clock_voltage_table(
0715 struct pp_hwmgr *hwmgr,
0716 phm_ppt_v1_mm_clock_voltage_dependency_table **tonga_mm_table,
0717 const ATOM_Tonga_MM_Dependency_Table * mm_dependency_table
0718 )
0719 {
0720 uint32_t i;
0721 const ATOM_Tonga_MM_Dependency_Record *mm_dependency_record;
0722 phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table;
0723 phm_ppt_v1_mm_clock_voltage_dependency_record *mm_table_record;
0724
0725 PP_ASSERT_WITH_CODE((0 != mm_dependency_table->ucNumEntries),
0726 "Invalid PowerPlay Table!", return -1);
0727 mm_table = kzalloc(struct_size(mm_table, entries, mm_dependency_table->ucNumEntries),
0728 GFP_KERNEL);
0729 if (!mm_table)
0730 return -ENOMEM;
0731
0732 mm_table->count = mm_dependency_table->ucNumEntries;
0733
0734 for (i = 0; i < mm_dependency_table->ucNumEntries; i++) {
0735 mm_dependency_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
0736 ATOM_Tonga_MM_Dependency_Record,
0737 entries, mm_dependency_table, i);
0738 mm_table_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
0739 phm_ppt_v1_mm_clock_voltage_dependency_record,
0740 entries, mm_table, i);
0741 mm_table_record->vddcInd = mm_dependency_record->ucVddcInd;
0742 mm_table_record->vddgfx_offset = le16_to_cpu(mm_dependency_record->usVddgfxOffset);
0743 mm_table_record->aclk = le32_to_cpu(mm_dependency_record->ulAClk);
0744 mm_table_record->samclock = le32_to_cpu(mm_dependency_record->ulSAMUClk);
0745 mm_table_record->eclk = le32_to_cpu(mm_dependency_record->ulEClk);
0746 mm_table_record->vclk = le32_to_cpu(mm_dependency_record->ulVClk);
0747 mm_table_record->dclk = le32_to_cpu(mm_dependency_record->ulDClk);
0748 }
0749
0750 *tonga_mm_table = mm_table;
0751
0752 return 0;
0753 }
0754
0755 static int get_gpio_table(struct pp_hwmgr *hwmgr,
0756 struct phm_ppt_v1_gpio_table **pp_tonga_gpio_table,
0757 const ATOM_Tonga_GPIO_Table *atom_gpio_table)
0758 {
0759 uint32_t table_size;
0760 struct phm_ppt_v1_gpio_table *pp_gpio_table;
0761 struct phm_ppt_v1_information *pp_table_information =
0762 (struct phm_ppt_v1_information *)(hwmgr->pptable);
0763
0764 table_size = sizeof(struct phm_ppt_v1_gpio_table);
0765 pp_gpio_table = kzalloc(table_size, GFP_KERNEL);
0766 if (!pp_gpio_table)
0767 return -ENOMEM;
0768
0769 if (pp_table_information->vdd_dep_on_sclk->count <
0770 atom_gpio_table->ucVRHotTriggeredSclkDpmIndex)
0771 PP_ASSERT_WITH_CODE(false,
0772 "SCLK DPM index for VRHot cannot exceed the total sclk level count!",);
0773 else
0774 pp_gpio_table->vrhot_triggered_sclk_dpm_index =
0775 atom_gpio_table->ucVRHotTriggeredSclkDpmIndex;
0776
0777 *pp_tonga_gpio_table = pp_gpio_table;
0778
0779 return 0;
0780 }
0781
0782
0783
0784
0785
0786
0787 static int init_clock_voltage_dependency(
0788 struct pp_hwmgr *hwmgr,
0789 const ATOM_Tonga_POWERPLAYTABLE *powerplay_table
0790 )
0791 {
0792 int result = 0;
0793 struct phm_ppt_v1_information *pp_table_information =
0794 (struct phm_ppt_v1_information *)(hwmgr->pptable);
0795
0796 const ATOM_Tonga_MM_Dependency_Table *mm_dependency_table =
0797 (const ATOM_Tonga_MM_Dependency_Table *)(((unsigned long) powerplay_table) +
0798 le16_to_cpu(powerplay_table->usMMDependencyTableOffset));
0799 const PPTable_Generic_SubTable_Header *pPowerTuneTable =
0800 (const PPTable_Generic_SubTable_Header *)(((unsigned long) powerplay_table) +
0801 le16_to_cpu(powerplay_table->usPowerTuneTableOffset));
0802 const ATOM_Tonga_MCLK_Dependency_Table *mclk_dep_table =
0803 (const ATOM_Tonga_MCLK_Dependency_Table *)(((unsigned long) powerplay_table) +
0804 le16_to_cpu(powerplay_table->usMclkDependencyTableOffset));
0805 const PPTable_Generic_SubTable_Header *sclk_dep_table =
0806 (const PPTable_Generic_SubTable_Header *)(((unsigned long) powerplay_table) +
0807 le16_to_cpu(powerplay_table->usSclkDependencyTableOffset));
0808 const ATOM_Tonga_Hard_Limit_Table *pHardLimits =
0809 (const ATOM_Tonga_Hard_Limit_Table *)(((unsigned long) powerplay_table) +
0810 le16_to_cpu(powerplay_table->usHardLimitTableOffset));
0811 const PPTable_Generic_SubTable_Header *pcie_table =
0812 (const PPTable_Generic_SubTable_Header *)(((unsigned long) powerplay_table) +
0813 le16_to_cpu(powerplay_table->usPCIETableOffset));
0814 const ATOM_Tonga_GPIO_Table *gpio_table =
0815 (const ATOM_Tonga_GPIO_Table *)(((unsigned long) powerplay_table) +
0816 le16_to_cpu(powerplay_table->usGPIOTableOffset));
0817
0818 pp_table_information->vdd_dep_on_sclk = NULL;
0819 pp_table_information->vdd_dep_on_mclk = NULL;
0820 pp_table_information->mm_dep_table = NULL;
0821 pp_table_information->pcie_table = NULL;
0822 pp_table_information->gpio_table = NULL;
0823
0824 if (powerplay_table->usMMDependencyTableOffset != 0)
0825 result = get_mm_clock_voltage_table(hwmgr,
0826 &pp_table_information->mm_dep_table, mm_dependency_table);
0827
0828 if (result == 0 && powerplay_table->usPowerTuneTableOffset != 0)
0829 result = get_cac_tdp_table(hwmgr,
0830 &pp_table_information->cac_dtp_table, pPowerTuneTable);
0831
0832 if (result == 0 && powerplay_table->usSclkDependencyTableOffset != 0)
0833 result = get_sclk_voltage_dependency_table(hwmgr,
0834 &pp_table_information->vdd_dep_on_sclk, sclk_dep_table);
0835
0836 if (result == 0 && powerplay_table->usMclkDependencyTableOffset != 0)
0837 result = get_mclk_voltage_dependency_table(hwmgr,
0838 &pp_table_information->vdd_dep_on_mclk, mclk_dep_table);
0839
0840 if (result == 0 && powerplay_table->usPCIETableOffset != 0)
0841 result = get_pcie_table(hwmgr,
0842 &pp_table_information->pcie_table, pcie_table);
0843
0844 if (result == 0 && powerplay_table->usHardLimitTableOffset != 0)
0845 result = get_hard_limits(hwmgr,
0846 &pp_table_information->max_clock_voltage_on_dc, pHardLimits);
0847
0848 hwmgr->dyn_state.max_clock_voltage_on_dc.sclk =
0849 pp_table_information->max_clock_voltage_on_dc.sclk;
0850 hwmgr->dyn_state.max_clock_voltage_on_dc.mclk =
0851 pp_table_information->max_clock_voltage_on_dc.mclk;
0852 hwmgr->dyn_state.max_clock_voltage_on_dc.vddc =
0853 pp_table_information->max_clock_voltage_on_dc.vddc;
0854 hwmgr->dyn_state.max_clock_voltage_on_dc.vddci =
0855 pp_table_information->max_clock_voltage_on_dc.vddci;
0856
0857 if (result == 0 && (NULL != pp_table_information->vdd_dep_on_mclk)
0858 && (0 != pp_table_information->vdd_dep_on_mclk->count))
0859 result = get_valid_clk(hwmgr, &pp_table_information->valid_mclk_values,
0860 pp_table_information->vdd_dep_on_mclk);
0861
0862 if (result == 0 && (NULL != pp_table_information->vdd_dep_on_sclk)
0863 && (0 != pp_table_information->vdd_dep_on_sclk->count))
0864 result = get_valid_clk(hwmgr, &pp_table_information->valid_sclk_values,
0865 pp_table_information->vdd_dep_on_sclk);
0866
0867 if (!result && gpio_table)
0868 result = get_gpio_table(hwmgr, &pp_table_information->gpio_table,
0869 gpio_table);
0870
0871 return result;
0872 }
0873
0874
0875
0876
0877
0878
0879
0880
0881
0882
0883
0884
0885 static int init_over_drive_limits(
0886 struct pp_hwmgr *hwmgr,
0887 const ATOM_Tonga_POWERPLAYTABLE *powerplay_table)
0888 {
0889 hwmgr->platform_descriptor.overdriveLimit.engineClock =
0890 le32_to_cpu(powerplay_table->ulMaxODEngineClock);
0891 hwmgr->platform_descriptor.overdriveLimit.memoryClock =
0892 le32_to_cpu(powerplay_table->ulMaxODMemoryClock);
0893
0894 hwmgr->platform_descriptor.minOverdriveVDDC = 0;
0895 hwmgr->platform_descriptor.maxOverdriveVDDC = 0;
0896 hwmgr->platform_descriptor.overdriveVDDCStep = 0;
0897
0898 return 0;
0899 }
0900
0901
0902
0903
0904
0905
0906
0907
0908 static int init_thermal_controller(
0909 struct pp_hwmgr *hwmgr,
0910 const ATOM_Tonga_POWERPLAYTABLE *powerplay_table
0911 )
0912 {
0913 const PPTable_Generic_SubTable_Header *fan_table;
0914 ATOM_Tonga_Thermal_Controller *thermal_controller;
0915
0916 thermal_controller = (ATOM_Tonga_Thermal_Controller *)
0917 (((unsigned long)powerplay_table) +
0918 le16_to_cpu(powerplay_table->usThermalControllerOffset));
0919 PP_ASSERT_WITH_CODE((0 != powerplay_table->usThermalControllerOffset),
0920 "Thermal controller table not set!", return -1);
0921
0922 hwmgr->thermal_controller.ucType = thermal_controller->ucType;
0923 hwmgr->thermal_controller.ucI2cLine = thermal_controller->ucI2cLine;
0924 hwmgr->thermal_controller.ucI2cAddress = thermal_controller->ucI2cAddress;
0925
0926 hwmgr->thermal_controller.fanInfo.bNoFan =
0927 (0 != (thermal_controller->ucFanParameters & ATOM_TONGA_PP_FANPARAMETERS_NOFAN));
0928
0929 hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution =
0930 thermal_controller->ucFanParameters &
0931 ATOM_TONGA_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK;
0932
0933 hwmgr->thermal_controller.fanInfo.ulMinRPM
0934 = thermal_controller->ucFanMinRPM * 100UL;
0935 hwmgr->thermal_controller.fanInfo.ulMaxRPM
0936 = thermal_controller->ucFanMaxRPM * 100UL;
0937
0938 set_hw_cap(
0939 hwmgr,
0940 ATOM_TONGA_PP_THERMALCONTROLLER_NONE != hwmgr->thermal_controller.ucType,
0941 PHM_PlatformCaps_ThermalController
0942 );
0943
0944 if (0 == powerplay_table->usFanTableOffset) {
0945 hwmgr->thermal_controller.use_hw_fan_control = 1;
0946 return 0;
0947 }
0948
0949 fan_table = (const PPTable_Generic_SubTable_Header *)
0950 (((unsigned long)powerplay_table) +
0951 le16_to_cpu(powerplay_table->usFanTableOffset));
0952
0953 PP_ASSERT_WITH_CODE((0 != powerplay_table->usFanTableOffset),
0954 "Fan table not set!", return -1);
0955 PP_ASSERT_WITH_CODE((0 < fan_table->ucRevId),
0956 "Unsupported fan table format!", return -1);
0957
0958 hwmgr->thermal_controller.advanceFanControlParameters.ulCycleDelay
0959 = 100000;
0960 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
0961 PHM_PlatformCaps_MicrocodeFanControl);
0962
0963 if (fan_table->ucRevId < 8) {
0964 const ATOM_Tonga_Fan_Table *tonga_fan_table =
0965 (ATOM_Tonga_Fan_Table *)fan_table;
0966 hwmgr->thermal_controller.advanceFanControlParameters.ucTHyst
0967 = tonga_fan_table->ucTHyst;
0968 hwmgr->thermal_controller.advanceFanControlParameters.usTMin
0969 = le16_to_cpu(tonga_fan_table->usTMin);
0970 hwmgr->thermal_controller.advanceFanControlParameters.usTMed
0971 = le16_to_cpu(tonga_fan_table->usTMed);
0972 hwmgr->thermal_controller.advanceFanControlParameters.usTHigh
0973 = le16_to_cpu(tonga_fan_table->usTHigh);
0974 hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin
0975 = le16_to_cpu(tonga_fan_table->usPWMMin);
0976 hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed
0977 = le16_to_cpu(tonga_fan_table->usPWMMed);
0978 hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh
0979 = le16_to_cpu(tonga_fan_table->usPWMHigh);
0980 hwmgr->thermal_controller.advanceFanControlParameters.usTMax
0981 = 10900;
0982 hwmgr->thermal_controller.advanceFanControlParameters.usTMax
0983 = le16_to_cpu(tonga_fan_table->usTMax);
0984 hwmgr->thermal_controller.advanceFanControlParameters.ucFanControlMode
0985 = tonga_fan_table->ucFanControlMode;
0986 hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanPWM
0987 = le16_to_cpu(tonga_fan_table->usFanPWMMax);
0988 hwmgr->thermal_controller.advanceFanControlParameters.usDefaultFanOutputSensitivity
0989 = 4836;
0990 hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity
0991 = le16_to_cpu(tonga_fan_table->usFanOutputSensitivity);
0992 hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanRPM
0993 = le16_to_cpu(tonga_fan_table->usFanRPMMax);
0994 hwmgr->thermal_controller.advanceFanControlParameters.ulMinFanSCLKAcousticLimit
0995 = (le32_to_cpu(tonga_fan_table->ulMinFanSCLKAcousticLimit) / 100);
0996 hwmgr->thermal_controller.advanceFanControlParameters.ucTargetTemperature
0997 = tonga_fan_table->ucTargetTemperature;
0998 hwmgr->thermal_controller.advanceFanControlParameters.ucMinimumPWMLimit
0999 = 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);
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);
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
1113
1114
1115
1116
1117
1118 static 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
1141 static 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
1190 static 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
1237 const 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
1242 int 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
1261
1262 static 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
1291 static 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
1306 static 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
1361
1362
1363
1364
1365
1366
1367
1368 int 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