2 * Copyright 2016 Advanced Micro Devices, Inc.
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
23 #include <linux/module.h>
24 #include <linux/slab.h>
27 #include "vega10_processpptables.h"
28 #include "ppatomfwctrl.h"
29 #include "atomfirmware.h"
31 #include "cgs_common.h"
32 #include "vega10_pptable.h"
34 static void set_hw_cap(struct pp_hwmgr *hwmgr, bool enable,
35 enum phm_platform_caps cap)
38 phm_cap_set(hwmgr->platform_descriptor.platformCaps, cap);
40 phm_cap_unset(hwmgr->platform_descriptor.platformCaps, cap);
43 static const void *get_powerplay_table(struct pp_hwmgr *hwmgr)
45 int index = GetIndexIntoMasterDataTable(powerplayinfo);
49 const void *table_address = hwmgr->soft_pp_table;
52 table_address = (ATOM_Vega10_POWERPLAYTABLE *)
53 cgs_atom_get_data_table(hwmgr->device, index,
56 hwmgr->soft_pp_table = table_address; /*Cache the result in RAM.*/
62 static int check_powerplay_tables(
63 struct pp_hwmgr *hwmgr,
64 const ATOM_Vega10_POWERPLAYTABLE *powerplay_table)
66 const ATOM_Vega10_State_Array *state_arrays;
68 state_arrays = (ATOM_Vega10_State_Array *)(((unsigned long)powerplay_table) +
69 le16_to_cpu(powerplay_table->usStateArrayOffset));
71 PP_ASSERT_WITH_CODE((powerplay_table->sHeader.format_revision >=
72 ATOM_Vega10_TABLE_REVISION_VEGA10),
73 "Unsupported PPTable format!", return -1);
74 PP_ASSERT_WITH_CODE(powerplay_table->usStateArrayOffset,
75 "State table is not set!", return -1);
76 PP_ASSERT_WITH_CODE(powerplay_table->sHeader.structuresize > 0,
77 "Invalid PowerPlay Table!", return -1);
78 PP_ASSERT_WITH_CODE(state_arrays->ucNumEntries > 0,
79 "Invalid PowerPlay Table!", return -1);
84 static int set_platform_caps(struct pp_hwmgr *hwmgr, uint32_t powerplay_caps)
88 0 != (powerplay_caps & ATOM_VEGA10_PP_PLATFORM_CAP_POWERPLAY),
89 PHM_PlatformCaps_PowerPlaySupport);
93 0 != (powerplay_caps & ATOM_VEGA10_PP_PLATFORM_CAP_SBIOSPOWERSOURCE),
94 PHM_PlatformCaps_BiosPowerSourceControl);
98 0 != (powerplay_caps & ATOM_VEGA10_PP_PLATFORM_CAP_HARDWAREDC),
99 PHM_PlatformCaps_AutomaticDCTransition);
103 0 != (powerplay_caps & ATOM_VEGA10_PP_PLATFORM_CAP_BACO),
104 PHM_PlatformCaps_BACO);
108 0 != (powerplay_caps & ATOM_VEGA10_PP_PLATFORM_COMBINE_PCC_WITH_THERMAL_SIGNAL),
109 PHM_PlatformCaps_CombinePCCWithThermalSignal);
114 static int init_thermal_controller(
115 struct pp_hwmgr *hwmgr,
116 const ATOM_Vega10_POWERPLAYTABLE *powerplay_table)
118 const ATOM_Vega10_Thermal_Controller *thermal_controller;
119 const ATOM_Vega10_Fan_Table *fan_table;
121 thermal_controller = (ATOM_Vega10_Thermal_Controller *)
122 (((unsigned long)powerplay_table) +
123 le16_to_cpu(powerplay_table->usThermalControllerOffset));
125 PP_ASSERT_WITH_CODE((powerplay_table->usThermalControllerOffset != 0),
126 "Thermal controller table not set!", return -1);
128 hwmgr->thermal_controller.ucType = thermal_controller->ucType;
129 hwmgr->thermal_controller.ucI2cLine = thermal_controller->ucI2cLine;
130 hwmgr->thermal_controller.ucI2cAddress = thermal_controller->ucI2cAddress;
132 hwmgr->thermal_controller.fanInfo.bNoFan =
133 (0 != (thermal_controller->ucFanParameters &
134 ATOM_VEGA10_PP_FANPARAMETERS_NOFAN));
136 hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution =
137 thermal_controller->ucFanParameters &
138 ATOM_VEGA10_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK;
140 hwmgr->thermal_controller.fanInfo.ulMinRPM =
141 thermal_controller->ucFanMinRPM * 100UL;
142 hwmgr->thermal_controller.fanInfo.ulMaxRPM =
143 thermal_controller->ucFanMaxRPM * 100UL;
147 ATOM_VEGA10_PP_THERMALCONTROLLER_NONE != hwmgr->thermal_controller.ucType,
148 PHM_PlatformCaps_ThermalController);
150 if (!powerplay_table->usFanTableOffset)
153 fan_table = (const ATOM_Vega10_Fan_Table *)
154 (((unsigned long)powerplay_table) +
155 le16_to_cpu(powerplay_table->usFanTableOffset));
157 PP_ASSERT_WITH_CODE((fan_table->ucRevId >= 8),
158 "Invalid Input Fan Table!", return -1);
160 hwmgr->thermal_controller.advanceFanControlParameters.ulCycleDelay
162 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
163 PHM_PlatformCaps_MicrocodeFanControl);
165 hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity =
166 le16_to_cpu(fan_table->usFanOutputSensitivity);
167 hwmgr->thermal_controller.advanceFanControlParameters.usMaxFanRPM =
168 le16_to_cpu(fan_table->usFanRPMMax);
169 hwmgr->thermal_controller.advanceFanControlParameters.usFanRPMMaxLimit =
170 le16_to_cpu(fan_table->usThrottlingRPM);
171 hwmgr->thermal_controller.advanceFanControlParameters.ulMinFanSCLKAcousticLimit =
172 le32_to_cpu((uint32_t)(fan_table->usFanAcousticLimit));
173 hwmgr->thermal_controller.advanceFanControlParameters.usTMax =
174 le16_to_cpu(fan_table->usTargetTemperature);
175 hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin =
176 le16_to_cpu(fan_table->usMinimumPWMLimit);
177 hwmgr->thermal_controller.advanceFanControlParameters.ulTargetGfxClk =
178 le32_to_cpu((uint32_t)(fan_table->usTargetGfxClk));
179 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainEdge =
180 le16_to_cpu(fan_table->usFanGainEdge);
181 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainHotspot =
182 le16_to_cpu(fan_table->usFanGainHotspot);
183 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainLiquid =
184 le16_to_cpu(fan_table->usFanGainLiquid);
185 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainVrVddc =
186 le16_to_cpu(fan_table->usFanGainVrVddc);
187 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainVrMvdd =
188 le16_to_cpu(fan_table->usFanGainVrMvdd);
189 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainPlx =
190 le16_to_cpu(fan_table->usFanGainPlx);
191 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainHbm =
192 le16_to_cpu(fan_table->usFanGainHbm);
194 hwmgr->thermal_controller.advanceFanControlParameters.ucEnableZeroRPM =
195 fan_table->ucEnableZeroRPM;
196 hwmgr->thermal_controller.advanceFanControlParameters.usZeroRPMStopTemperature =
197 le16_to_cpu(fan_table->usFanStopTemperature);
198 hwmgr->thermal_controller.advanceFanControlParameters.usZeroRPMStartTemperature =
199 le16_to_cpu(fan_table->usFanStartTemperature);
204 static int init_over_drive_limits(
205 struct pp_hwmgr *hwmgr,
206 const ATOM_Vega10_POWERPLAYTABLE *powerplay_table)
208 hwmgr->platform_descriptor.overdriveLimit.engineClock =
209 le32_to_cpu(powerplay_table->ulMaxODEngineClock);
210 hwmgr->platform_descriptor.overdriveLimit.memoryClock =
211 le32_to_cpu(powerplay_table->ulMaxODMemoryClock);
213 hwmgr->platform_descriptor.minOverdriveVDDC = 0;
214 hwmgr->platform_descriptor.maxOverdriveVDDC = 0;
215 hwmgr->platform_descriptor.overdriveVDDCStep = 0;
217 if (hwmgr->platform_descriptor.overdriveLimit.engineClock > 0 &&
218 hwmgr->platform_descriptor.overdriveLimit.memoryClock > 0) {
219 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
220 PHM_PlatformCaps_ACOverdriveSupport);
226 static int get_mm_clock_voltage_table(
227 struct pp_hwmgr *hwmgr,
228 phm_ppt_v1_mm_clock_voltage_dependency_table **vega10_mm_table,
229 const ATOM_Vega10_MM_Dependency_Table *mm_dependency_table)
231 uint32_t table_size, i;
232 const ATOM_Vega10_MM_Dependency_Record *mm_dependency_record;
233 phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table;
235 PP_ASSERT_WITH_CODE((mm_dependency_table->ucNumEntries != 0),
236 "Invalid PowerPlay Table!", return -1);
238 table_size = sizeof(uint32_t) +
239 sizeof(phm_ppt_v1_mm_clock_voltage_dependency_record) *
240 mm_dependency_table->ucNumEntries;
241 mm_table = (phm_ppt_v1_mm_clock_voltage_dependency_table *)
242 kzalloc(table_size, GFP_KERNEL);
247 mm_table->count = mm_dependency_table->ucNumEntries;
249 for (i = 0; i < mm_dependency_table->ucNumEntries; i++) {
250 mm_dependency_record = &mm_dependency_table->entries[i];
251 mm_table->entries[i].vddcInd = mm_dependency_record->ucVddcInd;
252 mm_table->entries[i].samclock =
253 le32_to_cpu(mm_dependency_record->ulPSPClk);
254 mm_table->entries[i].eclk = le32_to_cpu(mm_dependency_record->ulEClk);
255 mm_table->entries[i].vclk = le32_to_cpu(mm_dependency_record->ulVClk);
256 mm_table->entries[i].dclk = le32_to_cpu(mm_dependency_record->ulDClk);
259 *vega10_mm_table = mm_table;
264 static int get_tdp_table(
265 struct pp_hwmgr *hwmgr,
266 struct phm_tdp_table **info_tdp_table,
267 const Vega10_PPTable_Generic_SubTable_Header *table)
270 struct phm_tdp_table *tdp_table;
272 const ATOM_Vega10_PowerTune_Table *power_tune_table =
273 (ATOM_Vega10_PowerTune_Table *)table;
275 table_size = sizeof(uint32_t) + sizeof(struct phm_cac_tdp_table);
276 hwmgr->dyn_state.cac_dtp_table = (struct phm_cac_tdp_table *)
277 kzalloc(table_size, GFP_KERNEL);
279 if (!hwmgr->dyn_state.cac_dtp_table)
282 table_size = sizeof(uint32_t) + sizeof(struct phm_tdp_table);
283 tdp_table = kzalloc(table_size, GFP_KERNEL);
286 kfree(hwmgr->dyn_state.cac_dtp_table);
287 hwmgr->dyn_state.cac_dtp_table = NULL;
291 tdp_table->usMaximumPowerDeliveryLimit = le16_to_cpu(power_tune_table->usSocketPowerLimit);
292 tdp_table->usTDC = le16_to_cpu(power_tune_table->usTdcLimit);
293 tdp_table->usEDCLimit = le16_to_cpu(power_tune_table->usEdcLimit);
294 tdp_table->usSoftwareShutdownTemp =
295 le16_to_cpu(power_tune_table->usSoftwareShutdownTemp);
296 tdp_table->usTemperatureLimitTedge =
297 le16_to_cpu(power_tune_table->usTemperatureLimitTedge);
298 tdp_table->usTemperatureLimitHotspot =
299 le16_to_cpu(power_tune_table->usTemperatureLimitHotSpot);
300 tdp_table->usTemperatureLimitLiquid1 =
301 le16_to_cpu(power_tune_table->usTemperatureLimitLiquid1);
302 tdp_table->usTemperatureLimitLiquid2 =
303 le16_to_cpu(power_tune_table->usTemperatureLimitLiquid2);
304 tdp_table->usTemperatureLimitHBM =
305 le16_to_cpu(power_tune_table->usTemperatureLimitHBM);
306 tdp_table->usTemperatureLimitVrVddc =
307 le16_to_cpu(power_tune_table->usTemperatureLimitVrSoc);
308 tdp_table->usTemperatureLimitVrMvdd =
309 le16_to_cpu(power_tune_table->usTemperatureLimitVrMem);
310 tdp_table->usTemperatureLimitPlx =
311 le16_to_cpu(power_tune_table->usTemperatureLimitPlx);
312 tdp_table->ucLiquid1_I2C_address = power_tune_table->ucLiquid1_I2C_address;
313 tdp_table->ucLiquid2_I2C_address = power_tune_table->ucLiquid2_I2C_address;
314 tdp_table->ucLiquid_I2C_Line = power_tune_table->ucLiquid_I2C_LineSCL;
315 tdp_table->ucLiquid_I2C_LineSDA = power_tune_table->ucLiquid_I2C_LineSDA;
316 tdp_table->ucVr_I2C_address = power_tune_table->ucVr_I2C_address;
317 tdp_table->ucVr_I2C_Line = power_tune_table->ucVr_I2C_LineSCL;
318 tdp_table->ucVr_I2C_LineSDA = power_tune_table->ucVr_I2C_LineSDA;
319 tdp_table->ucPlx_I2C_address = power_tune_table->ucPlx_I2C_address;
320 tdp_table->ucPlx_I2C_Line = power_tune_table->ucPlx_I2C_LineSCL;
321 tdp_table->ucPlx_I2C_LineSDA = power_tune_table->ucPlx_I2C_LineSDA;
323 hwmgr->platform_descriptor.LoadLineSlope = power_tune_table->usLoadLineResistance;
325 *info_tdp_table = tdp_table;
330 static int get_socclk_voltage_dependency_table(
331 struct pp_hwmgr *hwmgr,
332 phm_ppt_v1_clock_voltage_dependency_table **pp_vega10_clk_dep_table,
333 const ATOM_Vega10_SOCCLK_Dependency_Table *clk_dep_table)
335 uint32_t table_size, i;
336 phm_ppt_v1_clock_voltage_dependency_table *clk_table;
338 PP_ASSERT_WITH_CODE(clk_dep_table->ucNumEntries,
339 "Invalid PowerPlay Table!", return -1);
341 table_size = sizeof(uint32_t) +
342 sizeof(phm_ppt_v1_clock_voltage_dependency_record) *
343 clk_dep_table->ucNumEntries;
345 clk_table = (phm_ppt_v1_clock_voltage_dependency_table *)
346 kzalloc(table_size, GFP_KERNEL);
351 clk_table->count = (uint32_t)clk_dep_table->ucNumEntries;
353 for (i = 0; i < clk_dep_table->ucNumEntries; i++) {
354 clk_table->entries[i].vddInd =
355 clk_dep_table->entries[i].ucVddInd;
356 clk_table->entries[i].clk =
357 le32_to_cpu(clk_dep_table->entries[i].ulClk);
360 *pp_vega10_clk_dep_table = clk_table;
365 static int get_mclk_voltage_dependency_table(
366 struct pp_hwmgr *hwmgr,
367 phm_ppt_v1_clock_voltage_dependency_table **pp_vega10_mclk_dep_table,
368 const ATOM_Vega10_MCLK_Dependency_Table *mclk_dep_table)
370 uint32_t table_size, i;
371 phm_ppt_v1_clock_voltage_dependency_table *mclk_table;
373 PP_ASSERT_WITH_CODE(mclk_dep_table->ucNumEntries,
374 "Invalid PowerPlay Table!", return -1);
376 table_size = sizeof(uint32_t) +
377 sizeof(phm_ppt_v1_clock_voltage_dependency_record) *
378 mclk_dep_table->ucNumEntries;
380 mclk_table = (phm_ppt_v1_clock_voltage_dependency_table *)
381 kzalloc(table_size, GFP_KERNEL);
386 mclk_table->count = (uint32_t)mclk_dep_table->ucNumEntries;
388 for (i = 0; i < mclk_dep_table->ucNumEntries; i++) {
389 mclk_table->entries[i].vddInd =
390 mclk_dep_table->entries[i].ucVddInd;
391 mclk_table->entries[i].vddciInd =
392 mclk_dep_table->entries[i].ucVddciInd;
393 mclk_table->entries[i].mvddInd =
394 mclk_dep_table->entries[i].ucVddMemInd;
395 mclk_table->entries[i].clk =
396 le32_to_cpu(mclk_dep_table->entries[i].ulMemClk);
399 *pp_vega10_mclk_dep_table = mclk_table;
404 static int get_gfxclk_voltage_dependency_table(
405 struct pp_hwmgr *hwmgr,
406 struct phm_ppt_v1_clock_voltage_dependency_table
407 **pp_vega10_clk_dep_table,
408 const ATOM_Vega10_GFXCLK_Dependency_Table *clk_dep_table)
410 uint32_t table_size, i;
411 struct phm_ppt_v1_clock_voltage_dependency_table
414 PP_ASSERT_WITH_CODE((clk_dep_table->ucNumEntries != 0),
415 "Invalid PowerPlay Table!", return -1);
417 table_size = sizeof(uint32_t) +
418 sizeof(phm_ppt_v1_clock_voltage_dependency_record) *
419 clk_dep_table->ucNumEntries;
421 clk_table = (struct phm_ppt_v1_clock_voltage_dependency_table *)
422 kzalloc(table_size, GFP_KERNEL);
427 clk_table->count = clk_dep_table->ucNumEntries;
429 for (i = 0; i < clk_table->count; i++) {
430 clk_table->entries[i].vddInd =
431 clk_dep_table->entries[i].ucVddInd;
432 clk_table->entries[i].clk =
433 le32_to_cpu(clk_dep_table->entries[i].ulClk);
434 clk_table->entries[i].cks_enable =
435 (((clk_dep_table->entries[i].usCKSVOffsetandDisable & 0x80)
436 >> 15) == 0) ? 1 : 0;
437 clk_table->entries[i].cks_voffset =
438 (clk_dep_table->entries[i].usCKSVOffsetandDisable & 0x7F);
439 clk_table->entries[i].sclk_offset =
440 clk_dep_table->entries[i].usAVFSOffset;
443 *pp_vega10_clk_dep_table = clk_table;
448 static int get_dcefclk_voltage_dependency_table(
449 struct pp_hwmgr *hwmgr,
450 struct phm_ppt_v1_clock_voltage_dependency_table
451 **pp_vega10_clk_dep_table,
452 const ATOM_Vega10_DCEFCLK_Dependency_Table *clk_dep_table)
454 uint32_t table_size, i;
455 struct phm_ppt_v1_clock_voltage_dependency_table
458 PP_ASSERT_WITH_CODE((clk_dep_table->ucNumEntries != 0),
459 "Invalid PowerPlay Table!", return -1);
461 table_size = sizeof(uint32_t) +
462 sizeof(phm_ppt_v1_clock_voltage_dependency_record) *
463 clk_dep_table->ucNumEntries;
465 clk_table = (struct phm_ppt_v1_clock_voltage_dependency_table *)
466 kzalloc(table_size, GFP_KERNEL);
471 clk_table->count = clk_dep_table->ucNumEntries;
473 for (i = 0; i < clk_table->count; i++) {
474 clk_table->entries[i].vddInd =
475 clk_dep_table->entries[i].ucVddInd;
476 clk_table->entries[i].clk =
477 le32_to_cpu(clk_dep_table->entries[i].ulClk);
480 *pp_vega10_clk_dep_table = clk_table;
485 static int get_pcie_table(struct pp_hwmgr *hwmgr,
486 struct phm_ppt_v1_pcie_table **vega10_pcie_table,
487 const Vega10_PPTable_Generic_SubTable_Header *table)
489 uint32_t table_size, i, pcie_count;
490 struct phm_ppt_v1_pcie_table *pcie_table;
491 struct phm_ppt_v2_information *table_info =
492 (struct phm_ppt_v2_information *)(hwmgr->pptable);
493 const ATOM_Vega10_PCIE_Table *atom_pcie_table =
494 (ATOM_Vega10_PCIE_Table *)table;
496 PP_ASSERT_WITH_CODE(atom_pcie_table->ucNumEntries,
497 "Invalid PowerPlay Table!",
500 table_size = sizeof(uint32_t) +
501 sizeof(struct phm_ppt_v1_pcie_record) *
502 atom_pcie_table->ucNumEntries;
504 pcie_table = (struct phm_ppt_v1_pcie_table *)
505 kzalloc(table_size, GFP_KERNEL);
510 pcie_count = table_info->vdd_dep_on_sclk->count;
511 if (atom_pcie_table->ucNumEntries <= pcie_count)
512 pcie_count = atom_pcie_table->ucNumEntries;
514 pr_info("Number of Pcie Entries exceed the number of"
515 " GFXCLK Dpm Levels!"
516 " Disregarding the excess entries...\n");
518 pcie_table->count = pcie_count;
520 for (i = 0; i < pcie_count; i++) {
521 pcie_table->entries[i].gen_speed =
522 atom_pcie_table->entries[i].ucPCIEGenSpeed;
523 pcie_table->entries[i].lane_width =
524 atom_pcie_table->entries[i].ucPCIELaneWidth;
525 pcie_table->entries[i].pcie_sclk =
526 atom_pcie_table->entries[i].ulLCLK;
529 *vega10_pcie_table = pcie_table;
534 static int get_hard_limits(
535 struct pp_hwmgr *hwmgr,
536 struct phm_clock_and_voltage_limits *limits,
537 const ATOM_Vega10_Hard_Limit_Table *limit_table)
539 PP_ASSERT_WITH_CODE(limit_table->ucNumEntries,
540 "Invalid PowerPlay Table!", return -1);
542 /* currently we always take entries[0] parameters */
543 limits->sclk = le32_to_cpu(limit_table->entries[0].ulSOCCLKLimit);
544 limits->mclk = le32_to_cpu(limit_table->entries[0].ulMCLKLimit);
545 limits->gfxclk = le32_to_cpu(limit_table->entries[0].ulGFXCLKLimit);
546 limits->vddc = le16_to_cpu(limit_table->entries[0].usVddcLimit);
547 limits->vddci = le16_to_cpu(limit_table->entries[0].usVddciLimit);
548 limits->vddmem = le16_to_cpu(limit_table->entries[0].usVddMemLimit);
553 static int get_valid_clk(
554 struct pp_hwmgr *hwmgr,
555 struct phm_clock_array **clk_table,
556 const phm_ppt_v1_clock_voltage_dependency_table *clk_volt_pp_table)
558 uint32_t table_size, i;
559 struct phm_clock_array *table;
561 PP_ASSERT_WITH_CODE(clk_volt_pp_table->count,
562 "Invalid PowerPlay Table!", return -1);
564 table_size = sizeof(uint32_t) +
565 sizeof(uint32_t) * clk_volt_pp_table->count;
567 table = kzalloc(table_size, GFP_KERNEL);
572 table->count = (uint32_t)clk_volt_pp_table->count;
574 for (i = 0; i < table->count; i++)
575 table->values[i] = (uint32_t)clk_volt_pp_table->entries[i].clk;
582 static int init_powerplay_extended_tables(
583 struct pp_hwmgr *hwmgr,
584 const ATOM_Vega10_POWERPLAYTABLE *powerplay_table)
587 struct phm_ppt_v2_information *pp_table_info =
588 (struct phm_ppt_v2_information *)(hwmgr->pptable);
590 const ATOM_Vega10_MM_Dependency_Table *mm_dependency_table =
591 (const ATOM_Vega10_MM_Dependency_Table *)
592 (((unsigned long) powerplay_table) +
593 le16_to_cpu(powerplay_table->usMMDependencyTableOffset));
594 const Vega10_PPTable_Generic_SubTable_Header *power_tune_table =
595 (const Vega10_PPTable_Generic_SubTable_Header *)
596 (((unsigned long) powerplay_table) +
597 le16_to_cpu(powerplay_table->usPowerTuneTableOffset));
598 const ATOM_Vega10_SOCCLK_Dependency_Table *socclk_dep_table =
599 (const ATOM_Vega10_SOCCLK_Dependency_Table *)
600 (((unsigned long) powerplay_table) +
601 le16_to_cpu(powerplay_table->usSocclkDependencyTableOffset));
602 const ATOM_Vega10_GFXCLK_Dependency_Table *gfxclk_dep_table =
603 (const ATOM_Vega10_GFXCLK_Dependency_Table *)
604 (((unsigned long) powerplay_table) +
605 le16_to_cpu(powerplay_table->usGfxclkDependencyTableOffset));
606 const ATOM_Vega10_DCEFCLK_Dependency_Table *dcefclk_dep_table =
607 (const ATOM_Vega10_DCEFCLK_Dependency_Table *)
608 (((unsigned long) powerplay_table) +
609 le16_to_cpu(powerplay_table->usDcefclkDependencyTableOffset));
610 const ATOM_Vega10_MCLK_Dependency_Table *mclk_dep_table =
611 (const ATOM_Vega10_MCLK_Dependency_Table *)
612 (((unsigned long) powerplay_table) +
613 le16_to_cpu(powerplay_table->usMclkDependencyTableOffset));
614 const ATOM_Vega10_Hard_Limit_Table *hard_limits =
615 (const ATOM_Vega10_Hard_Limit_Table *)
616 (((unsigned long) powerplay_table) +
617 le16_to_cpu(powerplay_table->usHardLimitTableOffset));
618 const Vega10_PPTable_Generic_SubTable_Header *pcie_table =
619 (const Vega10_PPTable_Generic_SubTable_Header *)
620 (((unsigned long) powerplay_table) +
621 le16_to_cpu(powerplay_table->usPCIETableOffset));
622 const ATOM_Vega10_PIXCLK_Dependency_Table *pixclk_dep_table =
623 (const ATOM_Vega10_PIXCLK_Dependency_Table *)
624 (((unsigned long) powerplay_table) +
625 le16_to_cpu(powerplay_table->usPixclkDependencyTableOffset));
626 const ATOM_Vega10_PHYCLK_Dependency_Table *phyclk_dep_table =
627 (const ATOM_Vega10_PHYCLK_Dependency_Table *)
628 (((unsigned long) powerplay_table) +
629 le16_to_cpu(powerplay_table->usPhyClkDependencyTableOffset));
630 const ATOM_Vega10_DISPCLK_Dependency_Table *dispclk_dep_table =
631 (const ATOM_Vega10_DISPCLK_Dependency_Table *)
632 (((unsigned long) powerplay_table) +
633 le16_to_cpu(powerplay_table->usDispClkDependencyTableOffset));
635 pp_table_info->vdd_dep_on_socclk = NULL;
636 pp_table_info->vdd_dep_on_sclk = NULL;
637 pp_table_info->vdd_dep_on_mclk = NULL;
638 pp_table_info->vdd_dep_on_dcefclk = NULL;
639 pp_table_info->mm_dep_table = NULL;
640 pp_table_info->tdp_table = NULL;
641 pp_table_info->vdd_dep_on_pixclk = NULL;
642 pp_table_info->vdd_dep_on_phyclk = NULL;
643 pp_table_info->vdd_dep_on_dispclk = NULL;
645 if (powerplay_table->usMMDependencyTableOffset)
646 result = get_mm_clock_voltage_table(hwmgr,
647 &pp_table_info->mm_dep_table,
648 mm_dependency_table);
650 if (!result && powerplay_table->usPowerTuneTableOffset)
651 result = get_tdp_table(hwmgr,
652 &pp_table_info->tdp_table,
655 if (!result && powerplay_table->usSocclkDependencyTableOffset)
656 result = get_socclk_voltage_dependency_table(hwmgr,
657 &pp_table_info->vdd_dep_on_socclk,
660 if (!result && powerplay_table->usGfxclkDependencyTableOffset)
661 result = get_gfxclk_voltage_dependency_table(hwmgr,
662 &pp_table_info->vdd_dep_on_sclk,
665 if (!result && powerplay_table->usPixclkDependencyTableOffset)
666 result = get_dcefclk_voltage_dependency_table(hwmgr,
667 &pp_table_info->vdd_dep_on_pixclk,
668 (const ATOM_Vega10_DCEFCLK_Dependency_Table*)
671 if (!result && powerplay_table->usPhyClkDependencyTableOffset)
672 result = get_dcefclk_voltage_dependency_table(hwmgr,
673 &pp_table_info->vdd_dep_on_phyclk,
674 (const ATOM_Vega10_DCEFCLK_Dependency_Table *)
677 if (!result && powerplay_table->usDispClkDependencyTableOffset)
678 result = get_dcefclk_voltage_dependency_table(hwmgr,
679 &pp_table_info->vdd_dep_on_dispclk,
680 (const ATOM_Vega10_DCEFCLK_Dependency_Table *)
683 if (!result && powerplay_table->usDcefclkDependencyTableOffset)
684 result = get_dcefclk_voltage_dependency_table(hwmgr,
685 &pp_table_info->vdd_dep_on_dcefclk,
688 if (!result && powerplay_table->usMclkDependencyTableOffset)
689 result = get_mclk_voltage_dependency_table(hwmgr,
690 &pp_table_info->vdd_dep_on_mclk,
693 if (!result && powerplay_table->usPCIETableOffset)
694 result = get_pcie_table(hwmgr,
695 &pp_table_info->pcie_table,
698 if (!result && powerplay_table->usHardLimitTableOffset)
699 result = get_hard_limits(hwmgr,
700 &pp_table_info->max_clock_voltage_on_dc,
703 hwmgr->dyn_state.max_clock_voltage_on_dc.sclk =
704 pp_table_info->max_clock_voltage_on_dc.sclk;
705 hwmgr->dyn_state.max_clock_voltage_on_dc.mclk =
706 pp_table_info->max_clock_voltage_on_dc.mclk;
707 hwmgr->dyn_state.max_clock_voltage_on_dc.vddc =
708 pp_table_info->max_clock_voltage_on_dc.vddc;
709 hwmgr->dyn_state.max_clock_voltage_on_dc.vddci =
710 pp_table_info->max_clock_voltage_on_dc.vddci;
713 pp_table_info->vdd_dep_on_socclk &&
714 pp_table_info->vdd_dep_on_socclk->count)
715 result = get_valid_clk(hwmgr,
716 &pp_table_info->valid_socclk_values,
717 pp_table_info->vdd_dep_on_socclk);
720 pp_table_info->vdd_dep_on_sclk &&
721 pp_table_info->vdd_dep_on_sclk->count)
722 result = get_valid_clk(hwmgr,
723 &pp_table_info->valid_sclk_values,
724 pp_table_info->vdd_dep_on_sclk);
727 pp_table_info->vdd_dep_on_dcefclk &&
728 pp_table_info->vdd_dep_on_dcefclk->count)
729 result = get_valid_clk(hwmgr,
730 &pp_table_info->valid_dcefclk_values,
731 pp_table_info->vdd_dep_on_dcefclk);
734 pp_table_info->vdd_dep_on_mclk &&
735 pp_table_info->vdd_dep_on_mclk->count)
736 result = get_valid_clk(hwmgr,
737 &pp_table_info->valid_mclk_values,
738 pp_table_info->vdd_dep_on_mclk);
743 static int get_vddc_lookup_table(
744 struct pp_hwmgr *hwmgr,
745 phm_ppt_v1_voltage_lookup_table **lookup_table,
746 const ATOM_Vega10_Voltage_Lookup_Table *vddc_lookup_pp_tables,
749 uint32_t table_size, i;
750 phm_ppt_v1_voltage_lookup_table *table;
752 PP_ASSERT_WITH_CODE((vddc_lookup_pp_tables->ucNumEntries != 0),
753 "Invalid SOC_VDDD Lookup Table!", return 1);
755 table_size = sizeof(uint32_t) +
756 sizeof(phm_ppt_v1_voltage_lookup_record) * max_levels;
758 table = (phm_ppt_v1_voltage_lookup_table *)
759 kzalloc(table_size, GFP_KERNEL);
764 table->count = vddc_lookup_pp_tables->ucNumEntries;
766 for (i = 0; i < vddc_lookup_pp_tables->ucNumEntries; i++)
767 table->entries[i].us_vdd =
768 le16_to_cpu(vddc_lookup_pp_tables->entries[i].usVdd);
770 *lookup_table = table;
775 static int init_dpm_2_parameters(
776 struct pp_hwmgr *hwmgr,
777 const ATOM_Vega10_POWERPLAYTABLE *powerplay_table)
780 struct phm_ppt_v2_information *pp_table_info =
781 (struct phm_ppt_v2_information *)(hwmgr->pptable);
782 uint32_t disable_power_control = 0;
784 pp_table_info->us_ulv_voltage_offset =
785 le16_to_cpu(powerplay_table->usUlvVoltageOffset);
787 pp_table_info->us_ulv_smnclk_did =
788 le16_to_cpu(powerplay_table->usUlvSmnclkDid);
789 pp_table_info->us_ulv_mp1clk_did =
790 le16_to_cpu(powerplay_table->usUlvMp1clkDid);
791 pp_table_info->us_ulv_gfxclk_bypass =
792 le16_to_cpu(powerplay_table->usUlvGfxclkBypass);
793 pp_table_info->us_gfxclk_slew_rate =
794 le16_to_cpu(powerplay_table->usGfxclkSlewRate);
795 pp_table_info->uc_gfx_dpm_voltage_mode =
796 le16_to_cpu(powerplay_table->ucGfxVoltageMode);
797 pp_table_info->uc_soc_dpm_voltage_mode =
798 le16_to_cpu(powerplay_table->ucSocVoltageMode);
799 pp_table_info->uc_uclk_dpm_voltage_mode =
800 le16_to_cpu(powerplay_table->ucUclkVoltageMode);
801 pp_table_info->uc_uvd_dpm_voltage_mode =
802 le16_to_cpu(powerplay_table->ucUvdVoltageMode);
803 pp_table_info->uc_vce_dpm_voltage_mode =
804 le16_to_cpu(powerplay_table->ucVceVoltageMode);
805 pp_table_info->uc_mp0_dpm_voltage_mode =
806 le16_to_cpu(powerplay_table->ucMp0VoltageMode);
807 pp_table_info->uc_dcef_dpm_voltage_mode =
808 le16_to_cpu(powerplay_table->ucDcefVoltageMode);
810 pp_table_info->ppm_parameter_table = NULL;
811 pp_table_info->vddc_lookup_table = NULL;
812 pp_table_info->vddmem_lookup_table = NULL;
813 pp_table_info->vddci_lookup_table = NULL;
816 hwmgr->platform_descriptor.TDPODLimit =
817 le16_to_cpu(powerplay_table->usPowerControlLimit);
818 hwmgr->platform_descriptor.TDPAdjustment = 0;
819 hwmgr->platform_descriptor.VidAdjustment = 0;
820 hwmgr->platform_descriptor.VidAdjustmentPolarity = 0;
821 hwmgr->platform_descriptor.VidMinLimit = 0;
822 hwmgr->platform_descriptor.VidMaxLimit = 1500000;
823 hwmgr->platform_descriptor.VidStep = 6250;
825 disable_power_control = 0;
826 if (!disable_power_control) {
827 /* enable TDP overdrive (PowerControl) feature as well if supported */
828 if (hwmgr->platform_descriptor.TDPODLimit)
829 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
830 PHM_PlatformCaps_PowerControl);
833 if (powerplay_table->usVddcLookupTableOffset) {
834 const ATOM_Vega10_Voltage_Lookup_Table *vddc_table =
835 (ATOM_Vega10_Voltage_Lookup_Table *)
836 (((unsigned long)powerplay_table) +
837 le16_to_cpu(powerplay_table->usVddcLookupTableOffset));
838 result = get_vddc_lookup_table(hwmgr,
839 &pp_table_info->vddc_lookup_table, vddc_table, 16);
842 if (powerplay_table->usVddmemLookupTableOffset) {
843 const ATOM_Vega10_Voltage_Lookup_Table *vdd_mem_table =
844 (ATOM_Vega10_Voltage_Lookup_Table *)
845 (((unsigned long)powerplay_table) +
846 le16_to_cpu(powerplay_table->usVddmemLookupTableOffset));
847 result = get_vddc_lookup_table(hwmgr,
848 &pp_table_info->vddmem_lookup_table, vdd_mem_table, 16);
851 if (powerplay_table->usVddciLookupTableOffset) {
852 const ATOM_Vega10_Voltage_Lookup_Table *vddci_table =
853 (ATOM_Vega10_Voltage_Lookup_Table *)
854 (((unsigned long)powerplay_table) +
855 le16_to_cpu(powerplay_table->usVddciLookupTableOffset));
856 result = get_vddc_lookup_table(hwmgr,
857 &pp_table_info->vddci_lookup_table, vddci_table, 16);
863 int vega10_pp_tables_initialize(struct pp_hwmgr *hwmgr)
866 const ATOM_Vega10_POWERPLAYTABLE *powerplay_table;
868 hwmgr->pptable = kzalloc(sizeof(struct phm_ppt_v2_information), GFP_KERNEL);
870 PP_ASSERT_WITH_CODE((NULL != hwmgr->pptable),
871 "Failed to allocate hwmgr->pptable!", return -ENOMEM);
873 powerplay_table = get_powerplay_table(hwmgr);
875 PP_ASSERT_WITH_CODE((NULL != powerplay_table),
876 "Missing PowerPlay Table!", return -1);
878 result = check_powerplay_tables(hwmgr, powerplay_table);
880 PP_ASSERT_WITH_CODE((result == 0),
881 "check_powerplay_tables failed", return result);
883 result = set_platform_caps(hwmgr,
884 le32_to_cpu(powerplay_table->ulPlatformCaps));
886 PP_ASSERT_WITH_CODE((result == 0),
887 "set_platform_caps failed", return result);
889 result = init_thermal_controller(hwmgr, powerplay_table);
891 PP_ASSERT_WITH_CODE((result == 0),
892 "init_thermal_controller failed", return result);
894 result = init_over_drive_limits(hwmgr, powerplay_table);
896 PP_ASSERT_WITH_CODE((result == 0),
897 "init_over_drive_limits failed", return result);
899 result = init_powerplay_extended_tables(hwmgr, powerplay_table);
901 PP_ASSERT_WITH_CODE((result == 0),
902 "init_powerplay_extended_tables failed", return result);
904 result = init_dpm_2_parameters(hwmgr, powerplay_table);
906 PP_ASSERT_WITH_CODE((result == 0),
907 "init_dpm_2_parameters failed", return result);
912 static int vega10_pp_tables_uninitialize(struct pp_hwmgr *hwmgr)
915 struct phm_ppt_v2_information *pp_table_info =
916 (struct phm_ppt_v2_information *)(hwmgr->pptable);
918 kfree(pp_table_info->vdd_dep_on_sclk);
919 pp_table_info->vdd_dep_on_sclk = NULL;
921 kfree(pp_table_info->vdd_dep_on_mclk);
922 pp_table_info->vdd_dep_on_mclk = NULL;
924 kfree(pp_table_info->valid_mclk_values);
925 pp_table_info->valid_mclk_values = NULL;
927 kfree(pp_table_info->valid_sclk_values);
928 pp_table_info->valid_sclk_values = NULL;
930 kfree(pp_table_info->vddc_lookup_table);
931 pp_table_info->vddc_lookup_table = NULL;
933 kfree(pp_table_info->vddmem_lookup_table);
934 pp_table_info->vddmem_lookup_table = NULL;
936 kfree(pp_table_info->vddci_lookup_table);
937 pp_table_info->vddci_lookup_table = NULL;
939 kfree(pp_table_info->ppm_parameter_table);
940 pp_table_info->ppm_parameter_table = NULL;
942 kfree(pp_table_info->mm_dep_table);
943 pp_table_info->mm_dep_table = NULL;
945 kfree(pp_table_info->cac_dtp_table);
946 pp_table_info->cac_dtp_table = NULL;
948 kfree(hwmgr->dyn_state.cac_dtp_table);
949 hwmgr->dyn_state.cac_dtp_table = NULL;
951 kfree(pp_table_info->tdp_table);
952 pp_table_info->tdp_table = NULL;
954 kfree(hwmgr->pptable);
955 hwmgr->pptable = NULL;
960 const struct pp_table_func vega10_pptable_funcs = {
961 .pptable_init = vega10_pp_tables_initialize,
962 .pptable_fini = vega10_pp_tables_uninitialize,
965 int vega10_get_number_of_powerplay_table_entries(struct pp_hwmgr *hwmgr)
967 const ATOM_Vega10_State_Array *state_arrays;
968 const ATOM_Vega10_POWERPLAYTABLE *pp_table = get_powerplay_table(hwmgr);
970 PP_ASSERT_WITH_CODE((NULL != pp_table),
971 "Missing PowerPlay Table!", return -1);
972 PP_ASSERT_WITH_CODE((pp_table->sHeader.format_revision >=
973 ATOM_Vega10_TABLE_REVISION_VEGA10),
974 "Incorrect PowerPlay table revision!", return -1);
976 state_arrays = (ATOM_Vega10_State_Array *)(((unsigned long)pp_table) +
977 le16_to_cpu(pp_table->usStateArrayOffset));
979 return (uint32_t)(state_arrays->ucNumEntries);
982 static uint32_t make_classification_flags(struct pp_hwmgr *hwmgr,
983 uint16_t classification, uint16_t classification2)
987 if (classification & ATOM_PPLIB_CLASSIFICATION_BOOT)
988 result |= PP_StateClassificationFlag_Boot;
990 if (classification & ATOM_PPLIB_CLASSIFICATION_THERMAL)
991 result |= PP_StateClassificationFlag_Thermal;
993 if (classification & ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE)
994 result |= PP_StateClassificationFlag_LimitedPowerSource;
996 if (classification & ATOM_PPLIB_CLASSIFICATION_REST)
997 result |= PP_StateClassificationFlag_Rest;
999 if (classification & ATOM_PPLIB_CLASSIFICATION_FORCED)
1000 result |= PP_StateClassificationFlag_Forced;
1002 if (classification & ATOM_PPLIB_CLASSIFICATION_ACPI)
1003 result |= PP_StateClassificationFlag_ACPI;
1005 if (classification2 & ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2)
1006 result |= PP_StateClassificationFlag_LimitedPowerSource_2;
1011 int vega10_get_powerplay_table_entry(struct pp_hwmgr *hwmgr,
1012 uint32_t entry_index, struct pp_power_state *power_state,
1013 int (*call_back_func)(struct pp_hwmgr *, void *,
1014 struct pp_power_state *, void *, uint32_t))
1017 const ATOM_Vega10_State_Array *state_arrays;
1018 const ATOM_Vega10_State *state_entry;
1019 const ATOM_Vega10_POWERPLAYTABLE *pp_table =
1020 get_powerplay_table(hwmgr);
1022 PP_ASSERT_WITH_CODE(pp_table, "Missing PowerPlay Table!",
1024 power_state->classification.bios_index = entry_index;
1026 if (pp_table->sHeader.format_revision >=
1027 ATOM_Vega10_TABLE_REVISION_VEGA10) {
1028 state_arrays = (ATOM_Vega10_State_Array *)
1029 (((unsigned long)pp_table) +
1030 le16_to_cpu(pp_table->usStateArrayOffset));
1032 PP_ASSERT_WITH_CODE(pp_table->usStateArrayOffset > 0,
1033 "Invalid PowerPlay Table State Array Offset.",
1035 PP_ASSERT_WITH_CODE(state_arrays->ucNumEntries > 0,
1036 "Invalid PowerPlay Table State Array.",
1038 PP_ASSERT_WITH_CODE((entry_index <= state_arrays->ucNumEntries),
1039 "Invalid PowerPlay Table State Array Entry.",
1042 state_entry = &(state_arrays->states[entry_index]);
1044 result = call_back_func(hwmgr, (void *)state_entry, power_state,
1046 make_classification_flags(hwmgr,
1047 le16_to_cpu(state_entry->usClassification),
1048 le16_to_cpu(state_entry->usClassification2)));
1051 if (!result && (power_state->classification.flags &
1052 PP_StateClassificationFlag_Boot))
1053 result = hwmgr->hwmgr_func->patch_boot_state(hwmgr, &(power_state->hardware));