2 * Copyright 2015 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.
24 #include <linux/module.h>
25 #include <linux/slab.h>
27 #include "process_pptables_v1_0.h"
28 #include "ppatomctrl.h"
31 #include "cgs_common.h"
32 #include "pptable_v1_0.h"
35 * Private Function used during initialization.
36 * @param hwmgr Pointer to the hardware manager.
37 * @param setIt A flag indication if the capability should be set (TRUE) or reset (FALSE).
38 * @param cap Which capability to set/reset.
40 static void set_hw_cap(struct pp_hwmgr
*hwmgr
, bool setIt
, enum phm_platform_caps cap
)
43 phm_cap_set(hwmgr
->platform_descriptor
.platformCaps
, cap
);
45 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
, cap
);
50 * Private Function used during initialization.
51 * @param hwmgr Pointer to the hardware manager.
52 * @param powerplay_caps the bit array (from BIOS) of capability bits.
53 * @exception the current implementation always returns 1.
55 static int set_platform_caps(struct pp_hwmgr
*hwmgr
, uint32_t powerplay_caps
)
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);
70 0 != (powerplay_caps
& ATOM_TONGA_PP_PLATFORM_CAP_POWERPLAY
),
71 PHM_PlatformCaps_PowerPlaySupport
76 0 != (powerplay_caps
& ATOM_TONGA_PP_PLATFORM_CAP_SBIOSPOWERSOURCE
),
77 PHM_PlatformCaps_BiosPowerSourceControl
82 0 != (powerplay_caps
& ATOM_TONGA_PP_PLATFORM_CAP_HARDWAREDC
),
83 PHM_PlatformCaps_AutomaticDCTransition
88 0 != (powerplay_caps
& ATOM_TONGA_PP_PLATFORM_CAP_MVDD_CONTROL
),
89 PHM_PlatformCaps_EnableMVDDControl
94 0 != (powerplay_caps
& ATOM_TONGA_PP_PLATFORM_CAP_VDDCI_CONTROL
),
95 PHM_PlatformCaps_ControlVDDCI
100 0 != (powerplay_caps
& ATOM_TONGA_PP_PLATFORM_CAP_VDDGFX_CONTROL
),
101 PHM_PlatformCaps_ControlVDDGFX
106 0 != (powerplay_caps
& ATOM_TONGA_PP_PLATFORM_CAP_BACO
),
107 PHM_PlatformCaps_BACO
112 0 != (powerplay_caps
& ATOM_TONGA_PP_PLATFORM_CAP_DISABLE_VOLTAGE_ISLAND
),
113 PHM_PlatformCaps_DisableVoltageIsland
118 0 != (powerplay_caps
& ATOM_TONGA_PP_PLATFORM_COMBINE_PCC_WITH_THERMAL_SIGNAL
),
119 PHM_PlatformCaps_CombinePCCWithThermalSignal
124 0 != (powerplay_caps
& ATOM_TONGA_PLATFORM_LOAD_POST_PRODUCTION_FIRMWARE
),
125 PHM_PlatformCaps_LoadPostProductionFirmware
132 * Private Function to get the PowerPlay Table Address.
134 static const void *get_powerplay_table(struct pp_hwmgr
*hwmgr
)
136 int index
= GetIndexIntoMasterTable(DATA
, PowerPlayInfo
);
140 void *table_address
= (void *)hwmgr
->soft_pp_table
;
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
;
150 return table_address
;
153 static int get_vddc_lookup_table(
154 struct pp_hwmgr
*hwmgr
,
155 phm_ppt_v1_voltage_lookup_table
**lookup_table
,
156 const ATOM_Tonga_Voltage_Lookup_Table
*vddc_lookup_pp_tables
,
160 uint32_t table_size
, i
;
161 phm_ppt_v1_voltage_lookup_table
*table
;
162 phm_ppt_v1_voltage_lookup_record
*record
;
163 ATOM_Tonga_Voltage_Lookup_Record
*atom_record
;
165 PP_ASSERT_WITH_CODE((0 != vddc_lookup_pp_tables
->ucNumEntries
),
166 "Invalid CAC Leakage PowerPlay Table!", return 1);
168 table_size
= sizeof(uint32_t) +
169 sizeof(phm_ppt_v1_voltage_lookup_record
) * max_levels
;
171 table
= kzalloc(table_size
, GFP_KERNEL
);
176 table
->count
= vddc_lookup_pp_tables
->ucNumEntries
;
178 for (i
= 0; i
< vddc_lookup_pp_tables
->ucNumEntries
; i
++) {
179 record
= GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
180 phm_ppt_v1_voltage_lookup_record
,
182 atom_record
= GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
183 ATOM_Tonga_Voltage_Lookup_Record
,
184 entries
, vddc_lookup_pp_tables
, i
);
185 record
->us_calculated
= 0;
186 record
->us_vdd
= le16_to_cpu(atom_record
->usVdd
);
187 record
->us_cac_low
= le16_to_cpu(atom_record
->usCACLow
);
188 record
->us_cac_mid
= le16_to_cpu(atom_record
->usCACMid
);
189 record
->us_cac_high
= le16_to_cpu(atom_record
->usCACHigh
);
192 *lookup_table
= table
;
198 * Private Function used during initialization.
199 * Initialize Platform Power Management Parameter table
200 * @param hwmgr Pointer to the hardware manager.
201 * @param atom_ppm_table Pointer to PPM table in VBIOS
203 static int get_platform_power_management_table(
204 struct pp_hwmgr
*hwmgr
,
205 ATOM_Tonga_PPM_Table
*atom_ppm_table
)
207 struct phm_ppm_table
*ptr
= kzalloc(sizeof(ATOM_Tonga_PPM_Table
), GFP_KERNEL
);
208 struct phm_ppt_v1_information
*pp_table_information
=
209 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
215 = atom_ppm_table
->ucPpmDesign
;
217 = atom_ppm_table
->usCpuCoreNumber
;
219 = atom_ppm_table
->ulPlatformTDP
;
220 ptr
->small_ac_platform_tdp
221 = atom_ppm_table
->ulSmallACPlatformTDP
;
223 = atom_ppm_table
->ulPlatformTDC
;
224 ptr
->small_ac_platform_tdc
225 = atom_ppm_table
->ulSmallACPlatformTDC
;
227 = atom_ppm_table
->ulApuTDP
;
229 = atom_ppm_table
->ulDGpuTDP
;
231 = atom_ppm_table
->ulDGpuUlvPower
;
233 = atom_ppm_table
->ulTjmax
;
235 pp_table_information
->ppm_parameter_table
= ptr
;
241 * Private Function used during initialization.
242 * Initialize TDP limits for DPM2
243 * @param hwmgr Pointer to the hardware manager.
244 * @param powerplay_table Pointer to the PowerPlay Table.
246 static int init_dpm_2_parameters(
247 struct pp_hwmgr
*hwmgr
,
248 const ATOM_Tonga_POWERPLAYTABLE
*powerplay_table
252 struct phm_ppt_v1_information
*pp_table_information
= (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
253 ATOM_Tonga_PPM_Table
*atom_ppm_table
;
254 uint32_t disable_ppm
= 0;
255 uint32_t disable_power_control
= 0;
257 pp_table_information
->us_ulv_voltage_offset
=
258 le16_to_cpu(powerplay_table
->usUlvVoltageOffset
);
260 pp_table_information
->ppm_parameter_table
= NULL
;
261 pp_table_information
->vddc_lookup_table
= NULL
;
262 pp_table_information
->vddgfx_lookup_table
= NULL
;
264 hwmgr
->platform_descriptor
.TDPODLimit
=
265 le16_to_cpu(powerplay_table
->usPowerControlLimit
);
266 hwmgr
->platform_descriptor
.TDPAdjustment
= 0;
267 hwmgr
->platform_descriptor
.VidAdjustment
= 0;
268 hwmgr
->platform_descriptor
.VidAdjustmentPolarity
= 0;
269 hwmgr
->platform_descriptor
.VidMinLimit
= 0;
270 hwmgr
->platform_descriptor
.VidMaxLimit
= 1500000;
271 hwmgr
->platform_descriptor
.VidStep
= 6250;
273 disable_power_control
= 0;
274 if (0 == disable_power_control
) {
275 /* enable TDP overdrive (PowerControl) feature as well if supported */
276 if (hwmgr
->platform_descriptor
.TDPODLimit
!= 0)
277 phm_cap_set(hwmgr
->platform_descriptor
.platformCaps
,
278 PHM_PlatformCaps_PowerControl
);
281 if (0 != powerplay_table
->usVddcLookupTableOffset
) {
282 const ATOM_Tonga_Voltage_Lookup_Table
*pVddcCACTable
=
283 (ATOM_Tonga_Voltage_Lookup_Table
*)(((unsigned long)powerplay_table
) +
284 le16_to_cpu(powerplay_table
->usVddcLookupTableOffset
));
286 result
= get_vddc_lookup_table(hwmgr
,
287 &pp_table_information
->vddc_lookup_table
, pVddcCACTable
, 16);
290 if (0 != powerplay_table
->usVddgfxLookupTableOffset
) {
291 const ATOM_Tonga_Voltage_Lookup_Table
*pVddgfxCACTable
=
292 (ATOM_Tonga_Voltage_Lookup_Table
*)(((unsigned long)powerplay_table
) +
293 le16_to_cpu(powerplay_table
->usVddgfxLookupTableOffset
));
295 result
= get_vddc_lookup_table(hwmgr
,
296 &pp_table_information
->vddgfx_lookup_table
, pVddgfxCACTable
, 16);
300 if (0 == disable_ppm
) {
301 atom_ppm_table
= (ATOM_Tonga_PPM_Table
*)
302 (((unsigned long)powerplay_table
) + le16_to_cpu(powerplay_table
->usPPMTableOffset
));
304 if (0 != powerplay_table
->usPPMTableOffset
) {
305 if (get_platform_power_management_table(hwmgr
, atom_ppm_table
) == 0) {
306 phm_cap_set(hwmgr
->platform_descriptor
.platformCaps
,
307 PHM_PlatformCaps_EnablePlatformPowerManagement
);
315 static int get_valid_clk(
316 struct pp_hwmgr
*hwmgr
,
317 struct phm_clock_array
**clk_table
,
318 phm_ppt_v1_clock_voltage_dependency_table
const *clk_volt_pp_table
321 uint32_t table_size
, i
;
322 struct phm_clock_array
*table
;
323 phm_ppt_v1_clock_voltage_dependency_record
*dep_record
;
325 PP_ASSERT_WITH_CODE((0 != clk_volt_pp_table
->count
),
326 "Invalid PowerPlay Table!", return -1);
328 table_size
= sizeof(uint32_t) +
329 sizeof(uint32_t) * clk_volt_pp_table
->count
;
331 table
= kzalloc(table_size
, GFP_KERNEL
);
336 table
->count
= (uint32_t)clk_volt_pp_table
->count
;
338 for (i
= 0; i
< table
->count
; i
++) {
339 dep_record
= GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
340 phm_ppt_v1_clock_voltage_dependency_record
,
341 entries
, clk_volt_pp_table
, i
);
342 table
->values
[i
] = (uint32_t)dep_record
->clk
;
349 static int get_hard_limits(
350 struct pp_hwmgr
*hwmgr
,
351 struct phm_clock_and_voltage_limits
*limits
,
352 ATOM_Tonga_Hard_Limit_Table
const *limitable
355 PP_ASSERT_WITH_CODE((0 != limitable
->ucNumEntries
), "Invalid PowerPlay Table!", return -1);
357 /* currently we always take entries[0] parameters */
358 limits
->sclk
= (uint32_t)limitable
->entries
[0].ulSCLKLimit
;
359 limits
->mclk
= (uint32_t)limitable
->entries
[0].ulMCLKLimit
;
360 limits
->vddc
= (uint16_t)limitable
->entries
[0].usVddcLimit
;
361 limits
->vddci
= (uint16_t)limitable
->entries
[0].usVddciLimit
;
362 limits
->vddgfx
= (uint16_t)limitable
->entries
[0].usVddgfxLimit
;
367 static int get_mclk_voltage_dependency_table(
368 struct pp_hwmgr
*hwmgr
,
369 phm_ppt_v1_clock_voltage_dependency_table
**pp_tonga_mclk_dep_table
,
370 ATOM_Tonga_MCLK_Dependency_Table
const *mclk_dep_table
373 uint32_t table_size
, i
;
374 phm_ppt_v1_clock_voltage_dependency_table
*mclk_table
;
375 phm_ppt_v1_clock_voltage_dependency_record
*mclk_table_record
;
376 ATOM_Tonga_MCLK_Dependency_Record
*mclk_dep_record
;
378 PP_ASSERT_WITH_CODE((0 != mclk_dep_table
->ucNumEntries
),
379 "Invalid PowerPlay Table!", return -1);
381 table_size
= sizeof(uint32_t) + sizeof(phm_ppt_v1_clock_voltage_dependency_record
)
382 * mclk_dep_table
->ucNumEntries
;
384 mclk_table
= kzalloc(table_size
, GFP_KERNEL
);
386 if (NULL
== mclk_table
)
389 mclk_table
->count
= (uint32_t)mclk_dep_table
->ucNumEntries
;
391 for (i
= 0; i
< mclk_dep_table
->ucNumEntries
; i
++) {
392 mclk_table_record
= GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
393 phm_ppt_v1_clock_voltage_dependency_record
,
394 entries
, mclk_table
, i
);
395 mclk_dep_record
= GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
396 ATOM_Tonga_MCLK_Dependency_Record
,
397 entries
, mclk_dep_table
, i
);
398 mclk_table_record
->vddInd
= mclk_dep_record
->ucVddcInd
;
399 mclk_table_record
->vdd_offset
= mclk_dep_record
->usVddgfxOffset
;
400 mclk_table_record
->vddci
= mclk_dep_record
->usVddci
;
401 mclk_table_record
->mvdd
= mclk_dep_record
->usMvdd
;
402 mclk_table_record
->clk
= mclk_dep_record
->ulMclk
;
405 *pp_tonga_mclk_dep_table
= mclk_table
;
410 static int get_sclk_voltage_dependency_table(
411 struct pp_hwmgr
*hwmgr
,
412 phm_ppt_v1_clock_voltage_dependency_table
**pp_tonga_sclk_dep_table
,
413 PPTable_Generic_SubTable_Header
const *sclk_dep_table
416 uint32_t table_size
, i
;
417 phm_ppt_v1_clock_voltage_dependency_table
*sclk_table
;
418 phm_ppt_v1_clock_voltage_dependency_record
*sclk_table_record
;
420 if (sclk_dep_table
->ucRevId
< 1) {
421 const ATOM_Tonga_SCLK_Dependency_Table
*tonga_table
=
422 (ATOM_Tonga_SCLK_Dependency_Table
*)sclk_dep_table
;
423 ATOM_Tonga_SCLK_Dependency_Record
*sclk_dep_record
;
425 PP_ASSERT_WITH_CODE((0 != tonga_table
->ucNumEntries
),
426 "Invalid PowerPlay Table!", return -1);
428 table_size
= sizeof(uint32_t) + sizeof(phm_ppt_v1_clock_voltage_dependency_record
)
429 * tonga_table
->ucNumEntries
;
431 sclk_table
= kzalloc(table_size
, GFP_KERNEL
);
433 if (NULL
== sclk_table
)
436 sclk_table
->count
= (uint32_t)tonga_table
->ucNumEntries
;
438 for (i
= 0; i
< tonga_table
->ucNumEntries
; i
++) {
439 sclk_dep_record
= GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
440 ATOM_Tonga_SCLK_Dependency_Record
,
441 entries
, tonga_table
, i
);
442 sclk_table_record
= GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
443 phm_ppt_v1_clock_voltage_dependency_record
,
444 entries
, sclk_table
, i
);
445 sclk_table_record
->vddInd
= sclk_dep_record
->ucVddInd
;
446 sclk_table_record
->vdd_offset
= sclk_dep_record
->usVddcOffset
;
447 sclk_table_record
->clk
= sclk_dep_record
->ulSclk
;
448 sclk_table_record
->cks_enable
=
449 (((sclk_dep_record
->ucCKSVOffsetandDisable
& 0x80) >> 7) == 0) ? 1 : 0;
450 sclk_table_record
->cks_voffset
= (sclk_dep_record
->ucCKSVOffsetandDisable
& 0x7F);
453 const ATOM_Polaris_SCLK_Dependency_Table
*polaris_table
=
454 (ATOM_Polaris_SCLK_Dependency_Table
*)sclk_dep_table
;
455 ATOM_Polaris_SCLK_Dependency_Record
*sclk_dep_record
;
457 PP_ASSERT_WITH_CODE((0 != polaris_table
->ucNumEntries
),
458 "Invalid PowerPlay Table!", return -1);
460 table_size
= sizeof(uint32_t) + sizeof(phm_ppt_v1_clock_voltage_dependency_record
)
461 * polaris_table
->ucNumEntries
;
463 sclk_table
= kzalloc(table_size
, GFP_KERNEL
);
465 if (NULL
== sclk_table
)
468 sclk_table
->count
= (uint32_t)polaris_table
->ucNumEntries
;
470 for (i
= 0; i
< polaris_table
->ucNumEntries
; i
++) {
471 sclk_dep_record
= GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
472 ATOM_Polaris_SCLK_Dependency_Record
,
473 entries
, polaris_table
, i
);
474 sclk_table_record
= GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
475 phm_ppt_v1_clock_voltage_dependency_record
,
476 entries
, sclk_table
, i
);
477 sclk_table_record
->vddInd
= sclk_dep_record
->ucVddInd
;
478 sclk_table_record
->vdd_offset
= sclk_dep_record
->usVddcOffset
;
479 sclk_table_record
->clk
= sclk_dep_record
->ulSclk
;
480 sclk_table_record
->cks_enable
=
481 (((sclk_dep_record
->ucCKSVOffsetandDisable
& 0x80) >> 7) == 0) ? 1 : 0;
482 sclk_table_record
->cks_voffset
= (sclk_dep_record
->ucCKSVOffsetandDisable
& 0x7F);
483 sclk_table_record
->sclk_offset
= sclk_dep_record
->ulSclkOffset
;
486 *pp_tonga_sclk_dep_table
= sclk_table
;
491 static int get_pcie_table(
492 struct pp_hwmgr
*hwmgr
,
493 phm_ppt_v1_pcie_table
**pp_tonga_pcie_table
,
494 PPTable_Generic_SubTable_Header
const *ptable
497 uint32_t table_size
, i
, pcie_count
;
498 phm_ppt_v1_pcie_table
*pcie_table
;
499 struct phm_ppt_v1_information
*pp_table_information
=
500 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
501 phm_ppt_v1_pcie_record
*pcie_record
;
503 if (ptable
->ucRevId
< 1) {
504 const ATOM_Tonga_PCIE_Table
*atom_pcie_table
= (ATOM_Tonga_PCIE_Table
*)ptable
;
505 ATOM_Tonga_PCIE_Record
*atom_pcie_record
;
507 PP_ASSERT_WITH_CODE((atom_pcie_table
->ucNumEntries
!= 0),
508 "Invalid PowerPlay Table!", return -1);
510 table_size
= sizeof(uint32_t) +
511 sizeof(phm_ppt_v1_pcie_record
) * atom_pcie_table
->ucNumEntries
;
513 pcie_table
= kzalloc(table_size
, GFP_KERNEL
);
515 if (pcie_table
== NULL
)
519 * Make sure the number of pcie entries are less than or equal to sclk dpm levels.
520 * Since first PCIE entry is for ULV, #pcie has to be <= SclkLevel + 1.
522 pcie_count
= (pp_table_information
->vdd_dep_on_sclk
->count
) + 1;
523 if ((uint32_t)atom_pcie_table
->ucNumEntries
<= pcie_count
)
524 pcie_count
= (uint32_t)atom_pcie_table
->ucNumEntries
;
526 pr_err("Number of Pcie Entries exceed the number of SCLK Dpm Levels! Disregarding the excess entries...\n");
528 pcie_table
->count
= pcie_count
;
529 for (i
= 0; i
< pcie_count
; i
++) {
530 pcie_record
= GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
531 phm_ppt_v1_pcie_record
,
532 entries
, pcie_table
, i
);
533 atom_pcie_record
= GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
534 ATOM_Tonga_PCIE_Record
,
535 entries
, atom_pcie_table
, i
);
536 pcie_record
->gen_speed
= atom_pcie_record
->ucPCIEGenSpeed
;
537 pcie_record
->lane_width
= atom_pcie_record
->usPCIELaneWidth
;
540 *pp_tonga_pcie_table
= pcie_table
;
542 /* Polaris10/Polaris11 and newer. */
543 const ATOM_Polaris10_PCIE_Table
*atom_pcie_table
= (ATOM_Polaris10_PCIE_Table
*)ptable
;
544 ATOM_Polaris10_PCIE_Record
*atom_pcie_record
;
546 PP_ASSERT_WITH_CODE((atom_pcie_table
->ucNumEntries
!= 0),
547 "Invalid PowerPlay Table!", return -1);
549 table_size
= sizeof(uint32_t) +
550 sizeof(phm_ppt_v1_pcie_record
) * atom_pcie_table
->ucNumEntries
;
552 pcie_table
= kzalloc(table_size
, GFP_KERNEL
);
554 if (pcie_table
== NULL
)
558 * Make sure the number of pcie entries are less than or equal to sclk dpm levels.
559 * Since first PCIE entry is for ULV, #pcie has to be <= SclkLevel + 1.
561 pcie_count
= (pp_table_information
->vdd_dep_on_sclk
->count
) + 1;
562 if ((uint32_t)atom_pcie_table
->ucNumEntries
<= pcie_count
)
563 pcie_count
= (uint32_t)atom_pcie_table
->ucNumEntries
;
565 pr_err("Number of Pcie Entries exceed the number of SCLK Dpm Levels! Disregarding the excess entries...\n");
567 pcie_table
->count
= pcie_count
;
569 for (i
= 0; i
< pcie_count
; i
++) {
570 pcie_record
= GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
571 phm_ppt_v1_pcie_record
,
572 entries
, pcie_table
, i
);
573 atom_pcie_record
= GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
574 ATOM_Polaris10_PCIE_Record
,
575 entries
, atom_pcie_table
, i
);
576 pcie_record
->gen_speed
= atom_pcie_record
->ucPCIEGenSpeed
;
577 pcie_record
->lane_width
= atom_pcie_record
->usPCIELaneWidth
;
578 pcie_record
->pcie_sclk
= atom_pcie_record
->ulPCIE_Sclk
;
581 *pp_tonga_pcie_table
= pcie_table
;
587 static int get_cac_tdp_table(
588 struct pp_hwmgr
*hwmgr
,
589 struct phm_cac_tdp_table
**cac_tdp_table
,
590 const PPTable_Generic_SubTable_Header
* table
594 struct phm_cac_tdp_table
*tdp_table
;
596 table_size
= sizeof(uint32_t) + sizeof(struct phm_cac_tdp_table
);
597 tdp_table
= kzalloc(table_size
, GFP_KERNEL
);
599 if (NULL
== tdp_table
)
602 hwmgr
->dyn_state
.cac_dtp_table
= kzalloc(table_size
, GFP_KERNEL
);
604 if (NULL
== hwmgr
->dyn_state
.cac_dtp_table
) {
609 if (table
->ucRevId
< 3) {
610 const ATOM_Tonga_PowerTune_Table
*tonga_table
=
611 (ATOM_Tonga_PowerTune_Table
*)table
;
612 tdp_table
->usTDP
= tonga_table
->usTDP
;
613 tdp_table
->usConfigurableTDP
=
614 tonga_table
->usConfigurableTDP
;
615 tdp_table
->usTDC
= tonga_table
->usTDC
;
616 tdp_table
->usBatteryPowerLimit
=
617 tonga_table
->usBatteryPowerLimit
;
618 tdp_table
->usSmallPowerLimit
=
619 tonga_table
->usSmallPowerLimit
;
620 tdp_table
->usLowCACLeakage
=
621 tonga_table
->usLowCACLeakage
;
622 tdp_table
->usHighCACLeakage
=
623 tonga_table
->usHighCACLeakage
;
624 tdp_table
->usMaximumPowerDeliveryLimit
=
625 tonga_table
->usMaximumPowerDeliveryLimit
;
626 tdp_table
->usDefaultTargetOperatingTemp
=
627 tonga_table
->usTjMax
;
628 tdp_table
->usTargetOperatingTemp
=
629 tonga_table
->usTjMax
; /*Set the initial temp to the same as default */
630 tdp_table
->usPowerTuneDataSetID
=
631 tonga_table
->usPowerTuneDataSetID
;
632 tdp_table
->usSoftwareShutdownTemp
=
633 tonga_table
->usSoftwareShutdownTemp
;
634 tdp_table
->usClockStretchAmount
=
635 tonga_table
->usClockStretchAmount
;
636 } else { /* Fiji and newer */
637 const ATOM_Fiji_PowerTune_Table
*fijitable
=
638 (ATOM_Fiji_PowerTune_Table
*)table
;
639 tdp_table
->usTDP
= fijitable
->usTDP
;
640 tdp_table
->usConfigurableTDP
= fijitable
->usConfigurableTDP
;
641 tdp_table
->usTDC
= fijitable
->usTDC
;
642 tdp_table
->usBatteryPowerLimit
= fijitable
->usBatteryPowerLimit
;
643 tdp_table
->usSmallPowerLimit
= fijitable
->usSmallPowerLimit
;
644 tdp_table
->usLowCACLeakage
= fijitable
->usLowCACLeakage
;
645 tdp_table
->usHighCACLeakage
= fijitable
->usHighCACLeakage
;
646 tdp_table
->usMaximumPowerDeliveryLimit
=
647 fijitable
->usMaximumPowerDeliveryLimit
;
648 tdp_table
->usDefaultTargetOperatingTemp
=
650 tdp_table
->usTargetOperatingTemp
=
651 fijitable
->usTjMax
; /*Set the initial temp to the same as default */
652 tdp_table
->usPowerTuneDataSetID
=
653 fijitable
->usPowerTuneDataSetID
;
654 tdp_table
->usSoftwareShutdownTemp
=
655 fijitable
->usSoftwareShutdownTemp
;
656 tdp_table
->usClockStretchAmount
=
657 fijitable
->usClockStretchAmount
;
658 tdp_table
->usTemperatureLimitHotspot
=
659 fijitable
->usTemperatureLimitHotspot
;
660 tdp_table
->usTemperatureLimitLiquid1
=
661 fijitable
->usTemperatureLimitLiquid1
;
662 tdp_table
->usTemperatureLimitLiquid2
=
663 fijitable
->usTemperatureLimitLiquid2
;
664 tdp_table
->usTemperatureLimitVrVddc
=
665 fijitable
->usTemperatureLimitVrVddc
;
666 tdp_table
->usTemperatureLimitVrMvdd
=
667 fijitable
->usTemperatureLimitVrMvdd
;
668 tdp_table
->usTemperatureLimitPlx
=
669 fijitable
->usTemperatureLimitPlx
;
670 tdp_table
->ucLiquid1_I2C_address
=
671 fijitable
->ucLiquid1_I2C_address
;
672 tdp_table
->ucLiquid2_I2C_address
=
673 fijitable
->ucLiquid2_I2C_address
;
674 tdp_table
->ucLiquid_I2C_Line
=
675 fijitable
->ucLiquid_I2C_Line
;
676 tdp_table
->ucVr_I2C_address
= fijitable
->ucVr_I2C_address
;
677 tdp_table
->ucVr_I2C_Line
= fijitable
->ucVr_I2C_Line
;
678 tdp_table
->ucPlx_I2C_address
= fijitable
->ucPlx_I2C_address
;
679 tdp_table
->ucPlx_I2C_Line
= fijitable
->ucPlx_I2C_Line
;
682 *cac_tdp_table
= tdp_table
;
687 static int get_mm_clock_voltage_table(
688 struct pp_hwmgr
*hwmgr
,
689 phm_ppt_v1_mm_clock_voltage_dependency_table
**tonga_mm_table
,
690 const ATOM_Tonga_MM_Dependency_Table
* mm_dependency_table
693 uint32_t table_size
, i
;
694 const ATOM_Tonga_MM_Dependency_Record
*mm_dependency_record
;
695 phm_ppt_v1_mm_clock_voltage_dependency_table
*mm_table
;
696 phm_ppt_v1_mm_clock_voltage_dependency_record
*mm_table_record
;
698 PP_ASSERT_WITH_CODE((0 != mm_dependency_table
->ucNumEntries
),
699 "Invalid PowerPlay Table!", return -1);
700 table_size
= sizeof(uint32_t) +
701 sizeof(phm_ppt_v1_mm_clock_voltage_dependency_record
)
702 * mm_dependency_table
->ucNumEntries
;
703 mm_table
= kzalloc(table_size
, GFP_KERNEL
);
705 if (NULL
== mm_table
)
708 mm_table
->count
= mm_dependency_table
->ucNumEntries
;
710 for (i
= 0; i
< mm_dependency_table
->ucNumEntries
; i
++) {
711 mm_dependency_record
= GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
712 ATOM_Tonga_MM_Dependency_Record
,
713 entries
, mm_dependency_table
, i
);
714 mm_table_record
= GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
715 phm_ppt_v1_mm_clock_voltage_dependency_record
,
716 entries
, mm_table
, i
);
717 mm_table_record
->vddcInd
= mm_dependency_record
->ucVddcInd
;
718 mm_table_record
->vddgfx_offset
= mm_dependency_record
->usVddgfxOffset
;
719 mm_table_record
->aclk
= mm_dependency_record
->ulAClk
;
720 mm_table_record
->samclock
= mm_dependency_record
->ulSAMUClk
;
721 mm_table_record
->eclk
= mm_dependency_record
->ulEClk
;
722 mm_table_record
->vclk
= mm_dependency_record
->ulVClk
;
723 mm_table_record
->dclk
= mm_dependency_record
->ulDClk
;
726 *tonga_mm_table
= mm_table
;
731 static int get_gpio_table(struct pp_hwmgr
*hwmgr
,
732 struct phm_ppt_v1_gpio_table
**pp_tonga_gpio_table
,
733 const ATOM_Tonga_GPIO_Table
*atom_gpio_table
)
736 struct phm_ppt_v1_gpio_table
*pp_gpio_table
;
737 struct phm_ppt_v1_information
*pp_table_information
=
738 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
740 table_size
= sizeof(struct phm_ppt_v1_gpio_table
);
741 pp_gpio_table
= kzalloc(table_size
, GFP_KERNEL
);
745 if (pp_table_information
->vdd_dep_on_sclk
->count
<
746 atom_gpio_table
->ucVRHotTriggeredSclkDpmIndex
)
747 PP_ASSERT_WITH_CODE(false,
748 "SCLK DPM index for VRHot cannot exceed the total sclk level count!",);
750 pp_gpio_table
->vrhot_triggered_sclk_dpm_index
=
751 atom_gpio_table
->ucVRHotTriggeredSclkDpmIndex
;
753 *pp_tonga_gpio_table
= pp_gpio_table
;
758 * Private Function used during initialization.
759 * Initialize clock voltage dependency
760 * @param hwmgr Pointer to the hardware manager.
761 * @param powerplay_table Pointer to the PowerPlay Table.
763 static int init_clock_voltage_dependency(
764 struct pp_hwmgr
*hwmgr
,
765 const ATOM_Tonga_POWERPLAYTABLE
*powerplay_table
769 struct phm_ppt_v1_information
*pp_table_information
=
770 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
772 const ATOM_Tonga_MM_Dependency_Table
*mm_dependency_table
=
773 (const ATOM_Tonga_MM_Dependency_Table
*)(((unsigned long) powerplay_table
) +
774 le16_to_cpu(powerplay_table
->usMMDependencyTableOffset
));
775 const PPTable_Generic_SubTable_Header
*pPowerTuneTable
=
776 (const PPTable_Generic_SubTable_Header
*)(((unsigned long) powerplay_table
) +
777 le16_to_cpu(powerplay_table
->usPowerTuneTableOffset
));
778 const ATOM_Tonga_MCLK_Dependency_Table
*mclk_dep_table
=
779 (const ATOM_Tonga_MCLK_Dependency_Table
*)(((unsigned long) powerplay_table
) +
780 le16_to_cpu(powerplay_table
->usMclkDependencyTableOffset
));
781 const PPTable_Generic_SubTable_Header
*sclk_dep_table
=
782 (const PPTable_Generic_SubTable_Header
*)(((unsigned long) powerplay_table
) +
783 le16_to_cpu(powerplay_table
->usSclkDependencyTableOffset
));
784 const ATOM_Tonga_Hard_Limit_Table
*pHardLimits
=
785 (const ATOM_Tonga_Hard_Limit_Table
*)(((unsigned long) powerplay_table
) +
786 le16_to_cpu(powerplay_table
->usHardLimitTableOffset
));
787 const PPTable_Generic_SubTable_Header
*pcie_table
=
788 (const PPTable_Generic_SubTable_Header
*)(((unsigned long) powerplay_table
) +
789 le16_to_cpu(powerplay_table
->usPCIETableOffset
));
790 const ATOM_Tonga_GPIO_Table
*gpio_table
=
791 (const ATOM_Tonga_GPIO_Table
*)(((unsigned long) powerplay_table
) +
792 le16_to_cpu(powerplay_table
->usGPIOTableOffset
));
794 pp_table_information
->vdd_dep_on_sclk
= NULL
;
795 pp_table_information
->vdd_dep_on_mclk
= NULL
;
796 pp_table_information
->mm_dep_table
= NULL
;
797 pp_table_information
->pcie_table
= NULL
;
798 pp_table_information
->gpio_table
= NULL
;
800 if (powerplay_table
->usMMDependencyTableOffset
!= 0)
801 result
= get_mm_clock_voltage_table(hwmgr
,
802 &pp_table_information
->mm_dep_table
, mm_dependency_table
);
804 if (result
== 0 && powerplay_table
->usPowerTuneTableOffset
!= 0)
805 result
= get_cac_tdp_table(hwmgr
,
806 &pp_table_information
->cac_dtp_table
, pPowerTuneTable
);
808 if (result
== 0 && powerplay_table
->usSclkDependencyTableOffset
!= 0)
809 result
= get_sclk_voltage_dependency_table(hwmgr
,
810 &pp_table_information
->vdd_dep_on_sclk
, sclk_dep_table
);
812 if (result
== 0 && powerplay_table
->usMclkDependencyTableOffset
!= 0)
813 result
= get_mclk_voltage_dependency_table(hwmgr
,
814 &pp_table_information
->vdd_dep_on_mclk
, mclk_dep_table
);
816 if (result
== 0 && powerplay_table
->usPCIETableOffset
!= 0)
817 result
= get_pcie_table(hwmgr
,
818 &pp_table_information
->pcie_table
, pcie_table
);
820 if (result
== 0 && powerplay_table
->usHardLimitTableOffset
!= 0)
821 result
= get_hard_limits(hwmgr
,
822 &pp_table_information
->max_clock_voltage_on_dc
, pHardLimits
);
824 hwmgr
->dyn_state
.max_clock_voltage_on_dc
.sclk
=
825 pp_table_information
->max_clock_voltage_on_dc
.sclk
;
826 hwmgr
->dyn_state
.max_clock_voltage_on_dc
.mclk
=
827 pp_table_information
->max_clock_voltage_on_dc
.mclk
;
828 hwmgr
->dyn_state
.max_clock_voltage_on_dc
.vddc
=
829 pp_table_information
->max_clock_voltage_on_dc
.vddc
;
830 hwmgr
->dyn_state
.max_clock_voltage_on_dc
.vddci
=
831 pp_table_information
->max_clock_voltage_on_dc
.vddci
;
833 if (result
== 0 && (NULL
!= pp_table_information
->vdd_dep_on_mclk
)
834 && (0 != pp_table_information
->vdd_dep_on_mclk
->count
))
835 result
= get_valid_clk(hwmgr
, &pp_table_information
->valid_mclk_values
,
836 pp_table_information
->vdd_dep_on_mclk
);
838 if (result
== 0 && (NULL
!= pp_table_information
->vdd_dep_on_sclk
)
839 && (0 != pp_table_information
->vdd_dep_on_sclk
->count
))
840 result
= get_valid_clk(hwmgr
, &pp_table_information
->valid_sclk_values
,
841 pp_table_information
->vdd_dep_on_sclk
);
843 if (!result
&& gpio_table
)
844 result
= get_gpio_table(hwmgr
, &pp_table_information
->gpio_table
,
850 /** Retrieves the (signed) Overdrive limits from VBIOS.
851 * The max engine clock, memory clock and max temperature come from the firmware info table.
853 * The information is placed into the platform descriptor.
855 * @param hwmgr source of the VBIOS table and owner of the platform descriptor to be updated.
856 * @param powerplay_table the address of the PowerPlay table.
858 * @return 1 as long as the firmware info table was present and of a supported version.
860 static int init_over_drive_limits(
861 struct pp_hwmgr
*hwmgr
,
862 const ATOM_Tonga_POWERPLAYTABLE
*powerplay_table
)
864 hwmgr
->platform_descriptor
.overdriveLimit
.engineClock
=
865 le32_to_cpu(powerplay_table
->ulMaxODEngineClock
);
866 hwmgr
->platform_descriptor
.overdriveLimit
.memoryClock
=
867 le32_to_cpu(powerplay_table
->ulMaxODMemoryClock
);
869 hwmgr
->platform_descriptor
.minOverdriveVDDC
= 0;
870 hwmgr
->platform_descriptor
.maxOverdriveVDDC
= 0;
871 hwmgr
->platform_descriptor
.overdriveVDDCStep
= 0;
877 * Private Function used during initialization.
878 * Inspect the PowerPlay table for obvious signs of corruption.
879 * @param hwmgr Pointer to the hardware manager.
880 * @param powerplay_table Pointer to the PowerPlay Table.
881 * @exception This implementation always returns 1.
883 static int init_thermal_controller(
884 struct pp_hwmgr
*hwmgr
,
885 const ATOM_Tonga_POWERPLAYTABLE
*powerplay_table
888 const PPTable_Generic_SubTable_Header
*fan_table
;
889 ATOM_Tonga_Thermal_Controller
*thermal_controller
;
891 thermal_controller
= (ATOM_Tonga_Thermal_Controller
*)
892 (((unsigned long)powerplay_table
) +
893 le16_to_cpu(powerplay_table
->usThermalControllerOffset
));
894 PP_ASSERT_WITH_CODE((0 != powerplay_table
->usThermalControllerOffset
),
895 "Thermal controller table not set!", return -1);
897 hwmgr
->thermal_controller
.ucType
= thermal_controller
->ucType
;
898 hwmgr
->thermal_controller
.ucI2cLine
= thermal_controller
->ucI2cLine
;
899 hwmgr
->thermal_controller
.ucI2cAddress
= thermal_controller
->ucI2cAddress
;
901 hwmgr
->thermal_controller
.fanInfo
.bNoFan
=
902 (0 != (thermal_controller
->ucFanParameters
& ATOM_TONGA_PP_FANPARAMETERS_NOFAN
));
904 hwmgr
->thermal_controller
.fanInfo
.ucTachometerPulsesPerRevolution
=
905 thermal_controller
->ucFanParameters
&
906 ATOM_TONGA_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK
;
908 hwmgr
->thermal_controller
.fanInfo
.ulMinRPM
909 = thermal_controller
->ucFanMinRPM
* 100UL;
910 hwmgr
->thermal_controller
.fanInfo
.ulMaxRPM
911 = thermal_controller
->ucFanMaxRPM
* 100UL;
915 ATOM_TONGA_PP_THERMALCONTROLLER_NONE
!= hwmgr
->thermal_controller
.ucType
,
916 PHM_PlatformCaps_ThermalController
919 if (0 == powerplay_table
->usFanTableOffset
)
922 fan_table
= (const PPTable_Generic_SubTable_Header
*)
923 (((unsigned long)powerplay_table
) +
924 le16_to_cpu(powerplay_table
->usFanTableOffset
));
926 PP_ASSERT_WITH_CODE((0 != powerplay_table
->usFanTableOffset
),
927 "Fan table not set!", return -1);
928 PP_ASSERT_WITH_CODE((0 < fan_table
->ucRevId
),
929 "Unsupported fan table format!", return -1);
931 hwmgr
->thermal_controller
.advanceFanControlParameters
.ulCycleDelay
933 phm_cap_set(hwmgr
->platform_descriptor
.platformCaps
,
934 PHM_PlatformCaps_MicrocodeFanControl
);
936 if (fan_table
->ucRevId
< 8) {
937 const ATOM_Tonga_Fan_Table
*tonga_fan_table
=
938 (ATOM_Tonga_Fan_Table
*)fan_table
;
939 hwmgr
->thermal_controller
.advanceFanControlParameters
.ucTHyst
940 = tonga_fan_table
->ucTHyst
;
941 hwmgr
->thermal_controller
.advanceFanControlParameters
.usTMin
942 = tonga_fan_table
->usTMin
;
943 hwmgr
->thermal_controller
.advanceFanControlParameters
.usTMed
944 = tonga_fan_table
->usTMed
;
945 hwmgr
->thermal_controller
.advanceFanControlParameters
.usTHigh
946 = tonga_fan_table
->usTHigh
;
947 hwmgr
->thermal_controller
.advanceFanControlParameters
.usPWMMin
948 = tonga_fan_table
->usPWMMin
;
949 hwmgr
->thermal_controller
.advanceFanControlParameters
.usPWMMed
950 = tonga_fan_table
->usPWMMed
;
951 hwmgr
->thermal_controller
.advanceFanControlParameters
.usPWMHigh
952 = tonga_fan_table
->usPWMHigh
;
953 hwmgr
->thermal_controller
.advanceFanControlParameters
.usTMax
954 = 10900; /* hard coded */
955 hwmgr
->thermal_controller
.advanceFanControlParameters
.usTMax
956 = tonga_fan_table
->usTMax
;
957 hwmgr
->thermal_controller
.advanceFanControlParameters
.ucFanControlMode
958 = tonga_fan_table
->ucFanControlMode
;
959 hwmgr
->thermal_controller
.advanceFanControlParameters
.usDefaultMaxFanPWM
960 = tonga_fan_table
->usFanPWMMax
;
961 hwmgr
->thermal_controller
.advanceFanControlParameters
.usDefaultFanOutputSensitivity
963 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanOutputSensitivity
964 = tonga_fan_table
->usFanOutputSensitivity
;
965 hwmgr
->thermal_controller
.advanceFanControlParameters
.usDefaultMaxFanRPM
966 = tonga_fan_table
->usFanRPMMax
;
967 hwmgr
->thermal_controller
.advanceFanControlParameters
.ulMinFanSCLKAcousticLimit
968 = (tonga_fan_table
->ulMinFanSCLKAcousticLimit
/ 100); /* PPTable stores it in 10Khz unit for 2 decimal places. SMC wants MHz. */
969 hwmgr
->thermal_controller
.advanceFanControlParameters
.ucTargetTemperature
970 = tonga_fan_table
->ucTargetTemperature
;
971 hwmgr
->thermal_controller
.advanceFanControlParameters
.ucMinimumPWMLimit
972 = tonga_fan_table
->ucMinimumPWMLimit
;
974 const ATOM_Fiji_Fan_Table
*fiji_fan_table
=
975 (ATOM_Fiji_Fan_Table
*)fan_table
;
976 hwmgr
->thermal_controller
.advanceFanControlParameters
.ucTHyst
977 = fiji_fan_table
->ucTHyst
;
978 hwmgr
->thermal_controller
.advanceFanControlParameters
.usTMin
979 = fiji_fan_table
->usTMin
;
980 hwmgr
->thermal_controller
.advanceFanControlParameters
.usTMed
981 = fiji_fan_table
->usTMed
;
982 hwmgr
->thermal_controller
.advanceFanControlParameters
.usTHigh
983 = fiji_fan_table
->usTHigh
;
984 hwmgr
->thermal_controller
.advanceFanControlParameters
.usPWMMin
985 = fiji_fan_table
->usPWMMin
;
986 hwmgr
->thermal_controller
.advanceFanControlParameters
.usPWMMed
987 = fiji_fan_table
->usPWMMed
;
988 hwmgr
->thermal_controller
.advanceFanControlParameters
.usPWMHigh
989 = fiji_fan_table
->usPWMHigh
;
990 hwmgr
->thermal_controller
.advanceFanControlParameters
.usTMax
991 = fiji_fan_table
->usTMax
;
992 hwmgr
->thermal_controller
.advanceFanControlParameters
.ucFanControlMode
993 = fiji_fan_table
->ucFanControlMode
;
994 hwmgr
->thermal_controller
.advanceFanControlParameters
.usDefaultMaxFanPWM
995 = fiji_fan_table
->usFanPWMMax
;
996 hwmgr
->thermal_controller
.advanceFanControlParameters
.usDefaultFanOutputSensitivity
998 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanOutputSensitivity
999 = fiji_fan_table
->usFanOutputSensitivity
;
1000 hwmgr
->thermal_controller
.advanceFanControlParameters
.usDefaultMaxFanRPM
1001 = fiji_fan_table
->usFanRPMMax
;
1002 hwmgr
->thermal_controller
.advanceFanControlParameters
.ulMinFanSCLKAcousticLimit
1003 = (fiji_fan_table
->ulMinFanSCLKAcousticLimit
/ 100); /* PPTable stores it in 10Khz unit for 2 decimal places. SMC wants MHz. */
1004 hwmgr
->thermal_controller
.advanceFanControlParameters
.ucTargetTemperature
1005 = fiji_fan_table
->ucTargetTemperature
;
1006 hwmgr
->thermal_controller
.advanceFanControlParameters
.ucMinimumPWMLimit
1007 = fiji_fan_table
->ucMinimumPWMLimit
;
1009 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanGainEdge
1010 = fiji_fan_table
->usFanGainEdge
;
1011 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanGainHotspot
1012 = fiji_fan_table
->usFanGainHotspot
;
1013 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanGainLiquid
1014 = fiji_fan_table
->usFanGainLiquid
;
1015 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanGainVrVddc
1016 = fiji_fan_table
->usFanGainVrVddc
;
1017 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanGainVrMvdd
1018 = fiji_fan_table
->usFanGainVrMvdd
;
1019 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanGainPlx
1020 = fiji_fan_table
->usFanGainPlx
;
1021 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanGainHbm
1022 = fiji_fan_table
->usFanGainHbm
;
1029 * Private Function used during initialization.
1030 * Inspect the PowerPlay table for obvious signs of corruption.
1031 * @param hwmgr Pointer to the hardware manager.
1032 * @param powerplay_table Pointer to the PowerPlay Table.
1033 * @exception 2 if the powerplay table is incorrect.
1035 static int check_powerplay_tables(
1036 struct pp_hwmgr
*hwmgr
,
1037 const ATOM_Tonga_POWERPLAYTABLE
*powerplay_table
1040 const ATOM_Tonga_State_Array
*state_arrays
;
1042 state_arrays
= (ATOM_Tonga_State_Array
*)(((unsigned long)powerplay_table
) +
1043 le16_to_cpu(powerplay_table
->usStateArrayOffset
));
1045 PP_ASSERT_WITH_CODE((ATOM_Tonga_TABLE_REVISION_TONGA
<=
1046 powerplay_table
->sHeader
.ucTableFormatRevision
),
1047 "Unsupported PPTable format!", return -1);
1048 PP_ASSERT_WITH_CODE((0 != powerplay_table
->usStateArrayOffset
),
1049 "State table is not set!", return -1);
1050 PP_ASSERT_WITH_CODE((0 < powerplay_table
->sHeader
.usStructureSize
),
1051 "Invalid PowerPlay Table!", return -1);
1052 PP_ASSERT_WITH_CODE((0 < state_arrays
->ucNumEntries
),
1053 "Invalid PowerPlay Table!", return -1);
1058 static int pp_tables_v1_0_initialize(struct pp_hwmgr
*hwmgr
)
1061 const ATOM_Tonga_POWERPLAYTABLE
*powerplay_table
;
1063 hwmgr
->pptable
= kzalloc(sizeof(struct phm_ppt_v1_information
), GFP_KERNEL
);
1065 PP_ASSERT_WITH_CODE((NULL
!= hwmgr
->pptable
),
1066 "Failed to allocate hwmgr->pptable!", return -ENOMEM
);
1068 memset(hwmgr
->pptable
, 0x00, sizeof(struct phm_ppt_v1_information
));
1070 powerplay_table
= get_powerplay_table(hwmgr
);
1072 PP_ASSERT_WITH_CODE((NULL
!= powerplay_table
),
1073 "Missing PowerPlay Table!", return -1);
1075 result
= check_powerplay_tables(hwmgr
, powerplay_table
);
1077 PP_ASSERT_WITH_CODE((result
== 0),
1078 "check_powerplay_tables failed", return result
);
1080 result
= set_platform_caps(hwmgr
,
1081 le32_to_cpu(powerplay_table
->ulPlatformCaps
));
1083 PP_ASSERT_WITH_CODE((result
== 0),
1084 "set_platform_caps failed", return result
);
1086 result
= init_thermal_controller(hwmgr
, powerplay_table
);
1088 PP_ASSERT_WITH_CODE((result
== 0),
1089 "init_thermal_controller failed", return result
);
1091 result
= init_over_drive_limits(hwmgr
, powerplay_table
);
1093 PP_ASSERT_WITH_CODE((result
== 0),
1094 "init_over_drive_limits failed", return result
);
1096 result
= init_clock_voltage_dependency(hwmgr
, powerplay_table
);
1098 PP_ASSERT_WITH_CODE((result
== 0),
1099 "init_clock_voltage_dependency failed", return result
);
1101 result
= init_dpm_2_parameters(hwmgr
, powerplay_table
);
1103 PP_ASSERT_WITH_CODE((result
== 0),
1104 "init_dpm_2_parameters failed", return result
);
1109 static int pp_tables_v1_0_uninitialize(struct pp_hwmgr
*hwmgr
)
1111 struct phm_ppt_v1_information
*pp_table_information
=
1112 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
1114 kfree(pp_table_information
->vdd_dep_on_sclk
);
1115 pp_table_information
->vdd_dep_on_sclk
= NULL
;
1117 kfree(pp_table_information
->vdd_dep_on_mclk
);
1118 pp_table_information
->vdd_dep_on_mclk
= NULL
;
1120 kfree(pp_table_information
->valid_mclk_values
);
1121 pp_table_information
->valid_mclk_values
= NULL
;
1123 kfree(pp_table_information
->valid_sclk_values
);
1124 pp_table_information
->valid_sclk_values
= NULL
;
1126 kfree(pp_table_information
->vddc_lookup_table
);
1127 pp_table_information
->vddc_lookup_table
= NULL
;
1129 kfree(pp_table_information
->vddgfx_lookup_table
);
1130 pp_table_information
->vddgfx_lookup_table
= NULL
;
1132 kfree(pp_table_information
->mm_dep_table
);
1133 pp_table_information
->mm_dep_table
= NULL
;
1135 kfree(pp_table_information
->cac_dtp_table
);
1136 pp_table_information
->cac_dtp_table
= NULL
;
1138 kfree(hwmgr
->dyn_state
.cac_dtp_table
);
1139 hwmgr
->dyn_state
.cac_dtp_table
= NULL
;
1141 kfree(pp_table_information
->ppm_parameter_table
);
1142 pp_table_information
->ppm_parameter_table
= NULL
;
1144 kfree(pp_table_information
->pcie_table
);
1145 pp_table_information
->pcie_table
= NULL
;
1147 kfree(pp_table_information
->gpio_table
);
1148 pp_table_information
->gpio_table
= NULL
;
1150 kfree(hwmgr
->pptable
);
1151 hwmgr
->pptable
= NULL
;
1156 const struct pp_table_func pptable_v1_0_funcs
= {
1157 .pptable_init
= pp_tables_v1_0_initialize
,
1158 .pptable_fini
= pp_tables_v1_0_uninitialize
,
1161 int get_number_of_powerplay_table_entries_v1_0(struct pp_hwmgr
*hwmgr
)
1163 ATOM_Tonga_State_Array
const *state_arrays
;
1164 const ATOM_Tonga_POWERPLAYTABLE
*pp_table
= get_powerplay_table(hwmgr
);
1166 PP_ASSERT_WITH_CODE((NULL
!= pp_table
),
1167 "Missing PowerPlay Table!", return -1);
1168 PP_ASSERT_WITH_CODE((pp_table
->sHeader
.ucTableFormatRevision
>=
1169 ATOM_Tonga_TABLE_REVISION_TONGA
),
1170 "Incorrect PowerPlay table revision!", return -1);
1172 state_arrays
= (ATOM_Tonga_State_Array
*)(((unsigned long)pp_table
) +
1173 le16_to_cpu(pp_table
->usStateArrayOffset
));
1175 return (uint32_t)(state_arrays
->ucNumEntries
);
1179 * Private function to convert flags stored in the BIOS to software flags in PowerPlay.
1181 static uint32_t make_classification_flags(struct pp_hwmgr
*hwmgr
,
1182 uint16_t classification
, uint16_t classification2
)
1184 uint32_t result
= 0;
1186 if (classification
& ATOM_PPLIB_CLASSIFICATION_BOOT
)
1187 result
|= PP_StateClassificationFlag_Boot
;
1189 if (classification
& ATOM_PPLIB_CLASSIFICATION_THERMAL
)
1190 result
|= PP_StateClassificationFlag_Thermal
;
1192 if (classification
& ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE
)
1193 result
|= PP_StateClassificationFlag_LimitedPowerSource
;
1195 if (classification
& ATOM_PPLIB_CLASSIFICATION_REST
)
1196 result
|= PP_StateClassificationFlag_Rest
;
1198 if (classification
& ATOM_PPLIB_CLASSIFICATION_FORCED
)
1199 result
|= PP_StateClassificationFlag_Forced
;
1201 if (classification
& ATOM_PPLIB_CLASSIFICATION_ACPI
)
1202 result
|= PP_StateClassificationFlag_ACPI
;
1204 if (classification2
& ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2
)
1205 result
|= PP_StateClassificationFlag_LimitedPowerSource_2
;
1210 static int ppt_get_num_of_vce_state_table_entries_v1_0(struct pp_hwmgr
*hwmgr
)
1212 const ATOM_Tonga_POWERPLAYTABLE
*pp_table
= get_powerplay_table(hwmgr
);
1213 const ATOM_Tonga_VCE_State_Table
*vce_state_table
;
1216 if (pp_table
== NULL
)
1219 vce_state_table
= (void *)pp_table
+
1220 le16_to_cpu(pp_table
->usVCEStateTableOffset
);
1222 return vce_state_table
->ucNumEntries
;
1225 static int ppt_get_vce_state_table_entry_v1_0(struct pp_hwmgr
*hwmgr
, uint32_t i
,
1226 struct amd_vce_state
*vce_state
, void **clock_info
, uint32_t *flag
)
1228 const ATOM_Tonga_VCE_State_Record
*vce_state_record
;
1229 ATOM_Tonga_SCLK_Dependency_Record
*sclk_dep_record
;
1230 ATOM_Tonga_MCLK_Dependency_Record
*mclk_dep_record
;
1231 ATOM_Tonga_MM_Dependency_Record
*mm_dep_record
;
1232 const ATOM_Tonga_POWERPLAYTABLE
*pptable
= get_powerplay_table(hwmgr
);
1233 const ATOM_Tonga_VCE_State_Table
*vce_state_table
= (ATOM_Tonga_VCE_State_Table
*)(((unsigned long)pptable
)
1234 + le16_to_cpu(pptable
->usVCEStateTableOffset
));
1235 const ATOM_Tonga_SCLK_Dependency_Table
*sclk_dep_table
= (ATOM_Tonga_SCLK_Dependency_Table
*)(((unsigned long)pptable
)
1236 + le16_to_cpu(pptable
->usSclkDependencyTableOffset
));
1237 const ATOM_Tonga_MCLK_Dependency_Table
*mclk_dep_table
= (ATOM_Tonga_MCLK_Dependency_Table
*)(((unsigned long)pptable
)
1238 + le16_to_cpu(pptable
->usMclkDependencyTableOffset
));
1239 const ATOM_Tonga_MM_Dependency_Table
*mm_dep_table
= (ATOM_Tonga_MM_Dependency_Table
*)(((unsigned long)pptable
)
1240 + le16_to_cpu(pptable
->usMMDependencyTableOffset
));
1242 PP_ASSERT_WITH_CODE((i
< vce_state_table
->ucNumEntries
),
1243 "Requested state entry ID is out of range!",
1246 vce_state_record
= GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
1247 ATOM_Tonga_VCE_State_Record
,
1248 entries
, vce_state_table
, i
);
1249 sclk_dep_record
= GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
1250 ATOM_Tonga_SCLK_Dependency_Record
,
1251 entries
, sclk_dep_table
,
1252 vce_state_record
->ucSCLKIndex
);
1253 mm_dep_record
= GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
1254 ATOM_Tonga_MM_Dependency_Record
,
1255 entries
, mm_dep_table
,
1256 vce_state_record
->ucVCEClockIndex
);
1257 *flag
= vce_state_record
->ucFlag
;
1259 vce_state
->evclk
= mm_dep_record
->ulEClk
;
1260 vce_state
->ecclk
= mm_dep_record
->ulEClk
;
1261 vce_state
->sclk
= sclk_dep_record
->ulSclk
;
1263 if (vce_state_record
->ucMCLKIndex
>= mclk_dep_table
->ucNumEntries
)
1264 mclk_dep_record
= GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
1265 ATOM_Tonga_MCLK_Dependency_Record
,
1266 entries
, mclk_dep_table
,
1267 mclk_dep_table
->ucNumEntries
- 1);
1269 mclk_dep_record
= GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
1270 ATOM_Tonga_MCLK_Dependency_Record
,
1271 entries
, mclk_dep_table
,
1272 vce_state_record
->ucMCLKIndex
);
1274 vce_state
->mclk
= mclk_dep_record
->ulMclk
;
1279 * Create a Power State out of an entry in the PowerPlay table.
1280 * This function is called by the hardware back-end.
1281 * @param hwmgr Pointer to the hardware manager.
1282 * @param entry_index The index of the entry to be extracted from the table.
1283 * @param power_state The address of the PowerState instance being created.
1284 * @return -1 if the entry cannot be retrieved.
1286 int get_powerplay_table_entry_v1_0(struct pp_hwmgr
*hwmgr
,
1287 uint32_t entry_index
, struct pp_power_state
*power_state
,
1288 int (*call_back_func
)(struct pp_hwmgr
*, void *,
1289 struct pp_power_state
*, void *, uint32_t))
1292 const ATOM_Tonga_State_Array
*state_arrays
;
1293 const ATOM_Tonga_State
*state_entry
;
1294 const ATOM_Tonga_POWERPLAYTABLE
*pp_table
= get_powerplay_table(hwmgr
);
1298 PP_ASSERT_WITH_CODE((NULL
!= pp_table
), "Missing PowerPlay Table!", return -1;);
1299 power_state
->classification
.bios_index
= entry_index
;
1301 if (pp_table
->sHeader
.ucTableFormatRevision
>=
1302 ATOM_Tonga_TABLE_REVISION_TONGA
) {
1303 state_arrays
= (ATOM_Tonga_State_Array
*)(((unsigned long)pp_table
) +
1304 le16_to_cpu(pp_table
->usStateArrayOffset
));
1306 PP_ASSERT_WITH_CODE((0 < pp_table
->usStateArrayOffset
),
1307 "Invalid PowerPlay Table State Array Offset.", return -1);
1308 PP_ASSERT_WITH_CODE((0 < state_arrays
->ucNumEntries
),
1309 "Invalid PowerPlay Table State Array.", return -1);
1310 PP_ASSERT_WITH_CODE((entry_index
<= state_arrays
->ucNumEntries
),
1311 "Invalid PowerPlay Table State Array Entry.", return -1);
1313 state_entry
= GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
1314 ATOM_Tonga_State
, entries
,
1315 state_arrays
, entry_index
);
1317 result
= call_back_func(hwmgr
, (void *)state_entry
, power_state
,
1319 make_classification_flags(hwmgr
,
1320 le16_to_cpu(state_entry
->usClassification
),
1321 le16_to_cpu(state_entry
->usClassification2
)));
1324 if (!result
&& (power_state
->classification
.flags
&
1325 PP_StateClassificationFlag_Boot
))
1326 result
= hwmgr
->hwmgr_func
->patch_boot_state(hwmgr
, &(power_state
->hardware
));
1328 hwmgr
->num_vce_state_tables
= i
= ppt_get_num_of_vce_state_table_entries_v1_0(hwmgr
);
1330 if ((i
!= 0) && (i
<= AMD_MAX_VCE_LEVELS
)) {
1331 for (j
= 0; j
< i
; j
++)
1332 ppt_get_vce_state_table_entry_v1_0(hwmgr
, j
, &(hwmgr
->vce_states
[j
]), NULL
, &flags
);