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.
23 #include <linux/module.h>
24 #include <linux/slab.h>
27 #include "tonga_processpptables.h"
28 #include "ppatomctrl.h"
32 #include "cgs_common.h"
33 #include "tonga_pptable.h"
36 * Private Function used during initialization.
37 * @param hwmgr Pointer to the hardware manager.
38 * @param setIt A flag indication if the capability should be set (TRUE) or reset (FALSE).
39 * @param cap Which capability to set/reset.
41 static void set_hw_cap(struct pp_hwmgr
*hwmgr
, bool setIt
, enum phm_platform_caps cap
)
44 phm_cap_set(hwmgr
->platform_descriptor
.platformCaps
, cap
);
46 phm_cap_unset(hwmgr
->platform_descriptor
.platformCaps
, cap
);
51 * Private Function used during initialization.
52 * @param hwmgr Pointer to the hardware manager.
53 * @param powerplay_caps the bit array (from BIOS) of capability bits.
54 * @exception the current implementation always returns 1.
56 static int set_platform_caps(struct pp_hwmgr
*hwmgr
, uint32_t powerplay_caps
)
58 PP_ASSERT_WITH_CODE((~powerplay_caps
& ____RETIRE16____
),
59 "ATOM_PP_PLATFORM_CAP_ASPM_L1 is not supported!", continue);
60 PP_ASSERT_WITH_CODE((~powerplay_caps
& ____RETIRE64____
),
61 "ATOM_PP_PLATFORM_CAP_GEMINIPRIMARY is not supported!", continue);
62 PP_ASSERT_WITH_CODE((~powerplay_caps
& ____RETIRE512____
),
63 "ATOM_PP_PLATFORM_CAP_SIDEPORTCONTROL is not supported!", continue);
64 PP_ASSERT_WITH_CODE((~powerplay_caps
& ____RETIRE1024____
),
65 "ATOM_PP_PLATFORM_CAP_TURNOFFPLL_ASPML1 is not supported!", continue);
66 PP_ASSERT_WITH_CODE((~powerplay_caps
& ____RETIRE2048____
),
67 "ATOM_PP_PLATFORM_CAP_HTLINKCONTROL is not supported!", continue);
71 0 != (powerplay_caps
& ATOM_TONGA_PP_PLATFORM_CAP_POWERPLAY
),
72 PHM_PlatformCaps_PowerPlaySupport
77 0 != (powerplay_caps
& ATOM_TONGA_PP_PLATFORM_CAP_SBIOSPOWERSOURCE
),
78 PHM_PlatformCaps_BiosPowerSourceControl
83 0 != (powerplay_caps
& ATOM_TONGA_PP_PLATFORM_CAP_HARDWAREDC
),
84 PHM_PlatformCaps_AutomaticDCTransition
89 0 != (powerplay_caps
& ATOM_TONGA_PP_PLATFORM_CAP_MVDD_CONTROL
),
90 PHM_PlatformCaps_EnableMVDDControl
95 0 != (powerplay_caps
& ATOM_TONGA_PP_PLATFORM_CAP_VDDCI_CONTROL
),
96 PHM_PlatformCaps_ControlVDDCI
101 0 != (powerplay_caps
& ATOM_TONGA_PP_PLATFORM_CAP_VDDGFX_CONTROL
),
102 PHM_PlatformCaps_ControlVDDGFX
107 0 != (powerplay_caps
& ATOM_TONGA_PP_PLATFORM_CAP_BACO
),
108 PHM_PlatformCaps_BACO
113 0 != (powerplay_caps
& ATOM_TONGA_PP_PLATFORM_CAP_DISABLE_VOLTAGE_ISLAND
),
114 PHM_PlatformCaps_DisableVoltageIsland
119 0 != (powerplay_caps
& ATOM_TONGA_PP_PLATFORM_COMBINE_PCC_WITH_THERMAL_SIGNAL
),
120 PHM_PlatformCaps_CombinePCCWithThermalSignal
125 0 != (powerplay_caps
& ATOM_TONGA_PLATFORM_LOAD_POST_PRODUCTION_FIRMWARE
),
126 PHM_PlatformCaps_LoadPostProductionFirmware
133 * Private Function to get the PowerPlay Table Address.
135 const void *get_powerplay_table(struct pp_hwmgr
*hwmgr
)
137 int index
= GetIndexIntoMasterTable(DATA
, PowerPlayInfo
);
141 void *table_address
= (void *)hwmgr
->soft_pp_table
;
143 if (!table_address
) {
144 table_address
= (ATOM_Tonga_POWERPLAYTABLE
*)
145 cgs_atom_get_data_table(hwmgr
->device
,
146 index
, &size
, &frev
, &crev
);
147 hwmgr
->soft_pp_table
= table_address
; /*Cache the result in RAM.*/
148 hwmgr
->soft_pp_table_size
= size
;
151 return table_address
;
154 static int get_vddc_lookup_table(
155 struct pp_hwmgr
*hwmgr
,
156 phm_ppt_v1_voltage_lookup_table
**lookup_table
,
157 const ATOM_Tonga_Voltage_Lookup_Table
*vddc_lookup_pp_tables
,
161 uint32_t table_size
, i
;
162 phm_ppt_v1_voltage_lookup_table
*table
;
164 PP_ASSERT_WITH_CODE((0 != vddc_lookup_pp_tables
->ucNumEntries
),
165 "Invalid CAC Leakage PowerPlay Table!", return 1);
167 table_size
= sizeof(uint32_t) +
168 sizeof(phm_ppt_v1_voltage_lookup_record
) * max_levels
;
170 table
= kzalloc(table_size
, GFP_KERNEL
);
175 memset(table
, 0x00, table_size
);
177 table
->count
= vddc_lookup_pp_tables
->ucNumEntries
;
179 for (i
= 0; i
< vddc_lookup_pp_tables
->ucNumEntries
; i
++) {
180 table
->entries
[i
].us_calculated
= 0;
181 table
->entries
[i
].us_vdd
=
182 vddc_lookup_pp_tables
->entries
[i
].usVdd
;
183 table
->entries
[i
].us_cac_low
=
184 vddc_lookup_pp_tables
->entries
[i
].usCACLow
;
185 table
->entries
[i
].us_cac_mid
=
186 vddc_lookup_pp_tables
->entries
[i
].usCACMid
;
187 table
->entries
[i
].us_cac_high
=
188 vddc_lookup_pp_tables
->entries
[i
].usCACHigh
;
191 *lookup_table
= table
;
197 * Private Function used during initialization.
198 * Initialize Platform Power Management Parameter table
199 * @param hwmgr Pointer to the hardware manager.
200 * @param atom_ppm_table Pointer to PPM table in VBIOS
202 static int get_platform_power_management_table(
203 struct pp_hwmgr
*hwmgr
,
204 ATOM_Tonga_PPM_Table
*atom_ppm_table
)
206 struct phm_ppm_table
*ptr
= kzalloc(sizeof(ATOM_Tonga_PPM_Table
), GFP_KERNEL
);
207 struct phm_ppt_v1_information
*pp_table_information
=
208 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
214 = atom_ppm_table
->ucPpmDesign
;
216 = atom_ppm_table
->usCpuCoreNumber
;
218 = atom_ppm_table
->ulPlatformTDP
;
219 ptr
->small_ac_platform_tdp
220 = atom_ppm_table
->ulSmallACPlatformTDP
;
222 = atom_ppm_table
->ulPlatformTDC
;
223 ptr
->small_ac_platform_tdc
224 = atom_ppm_table
->ulSmallACPlatformTDC
;
226 = atom_ppm_table
->ulApuTDP
;
228 = atom_ppm_table
->ulDGpuTDP
;
230 = atom_ppm_table
->ulDGpuUlvPower
;
232 = atom_ppm_table
->ulTjmax
;
234 pp_table_information
->ppm_parameter_table
= ptr
;
240 * Private Function used during initialization.
241 * Initialize TDP limits for DPM2
242 * @param hwmgr Pointer to the hardware manager.
243 * @param powerplay_table Pointer to the PowerPlay Table.
245 static int init_dpm_2_parameters(
246 struct pp_hwmgr
*hwmgr
,
247 const ATOM_Tonga_POWERPLAYTABLE
*powerplay_table
251 struct phm_ppt_v1_information
*pp_table_information
= (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
252 ATOM_Tonga_PPM_Table
*atom_ppm_table
;
253 uint32_t disable_ppm
= 0;
254 uint32_t disable_power_control
= 0;
256 pp_table_information
->us_ulv_voltage_offset
=
257 le16_to_cpu(powerplay_table
->usUlvVoltageOffset
);
259 pp_table_information
->ppm_parameter_table
= NULL
;
260 pp_table_information
->vddc_lookup_table
= NULL
;
261 pp_table_information
->vddgfx_lookup_table
= NULL
;
263 hwmgr
->platform_descriptor
.TDPODLimit
=
264 le16_to_cpu(powerplay_table
->usPowerControlLimit
);
265 hwmgr
->platform_descriptor
.TDPAdjustment
= 0;
266 hwmgr
->platform_descriptor
.VidAdjustment
= 0;
267 hwmgr
->platform_descriptor
.VidAdjustmentPolarity
= 0;
268 hwmgr
->platform_descriptor
.VidMinLimit
= 0;
269 hwmgr
->platform_descriptor
.VidMaxLimit
= 1500000;
270 hwmgr
->platform_descriptor
.VidStep
= 6250;
272 disable_power_control
= 0;
273 if (0 == disable_power_control
) {
274 /* enable TDP overdrive (PowerControl) feature as well if supported */
275 if (hwmgr
->platform_descriptor
.TDPODLimit
!= 0)
276 phm_cap_set(hwmgr
->platform_descriptor
.platformCaps
,
277 PHM_PlatformCaps_PowerControl
);
280 if (0 != powerplay_table
->usVddcLookupTableOffset
) {
281 const ATOM_Tonga_Voltage_Lookup_Table
*pVddcCACTable
=
282 (ATOM_Tonga_Voltage_Lookup_Table
*)(((unsigned long)powerplay_table
) +
283 le16_to_cpu(powerplay_table
->usVddcLookupTableOffset
));
285 result
= get_vddc_lookup_table(hwmgr
,
286 &pp_table_information
->vddc_lookup_table
, pVddcCACTable
, 16);
289 if (0 != powerplay_table
->usVddgfxLookupTableOffset
) {
290 const ATOM_Tonga_Voltage_Lookup_Table
*pVddgfxCACTable
=
291 (ATOM_Tonga_Voltage_Lookup_Table
*)(((unsigned long)powerplay_table
) +
292 le16_to_cpu(powerplay_table
->usVddgfxLookupTableOffset
));
294 result
= get_vddc_lookup_table(hwmgr
,
295 &pp_table_information
->vddgfx_lookup_table
, pVddgfxCACTable
, 16);
299 if (0 == disable_ppm
) {
300 atom_ppm_table
= (ATOM_Tonga_PPM_Table
*)
301 (((unsigned long)powerplay_table
) + le16_to_cpu(powerplay_table
->usPPMTableOffset
));
303 if (0 != powerplay_table
->usPPMTableOffset
) {
304 if (get_platform_power_management_table(hwmgr
, atom_ppm_table
) == 0) {
305 phm_cap_set(hwmgr
->platform_descriptor
.platformCaps
,
306 PHM_PlatformCaps_EnablePlatformPowerManagement
);
314 static int get_valid_clk(
315 struct pp_hwmgr
*hwmgr
,
316 struct phm_clock_array
**clk_table
,
317 const phm_ppt_v1_clock_voltage_dependency_table
* clk_volt_pp_table
320 uint32_t table_size
, i
;
321 struct phm_clock_array
*table
;
323 PP_ASSERT_WITH_CODE((0 != clk_volt_pp_table
->count
),
324 "Invalid PowerPlay Table!", return -1);
326 table_size
= sizeof(uint32_t) +
327 sizeof(uint32_t) * clk_volt_pp_table
->count
;
329 table
= kzalloc(table_size
, GFP_KERNEL
);
334 memset(table
, 0x00, table_size
);
336 table
->count
= (uint32_t)clk_volt_pp_table
->count
;
338 for (i
= 0; i
< table
->count
; i
++)
339 table
->values
[i
] = (uint32_t)clk_volt_pp_table
->entries
[i
].clk
;
346 static int get_hard_limits(
347 struct pp_hwmgr
*hwmgr
,
348 struct phm_clock_and_voltage_limits
*limits
,
349 const ATOM_Tonga_Hard_Limit_Table
* limitable
352 PP_ASSERT_WITH_CODE((0 != limitable
->ucNumEntries
), "Invalid PowerPlay Table!", return -1);
354 /* currently we always take entries[0] parameters */
355 limits
->sclk
= (uint32_t)limitable
->entries
[0].ulSCLKLimit
;
356 limits
->mclk
= (uint32_t)limitable
->entries
[0].ulMCLKLimit
;
357 limits
->vddc
= (uint16_t)limitable
->entries
[0].usVddcLimit
;
358 limits
->vddci
= (uint16_t)limitable
->entries
[0].usVddciLimit
;
359 limits
->vddgfx
= (uint16_t)limitable
->entries
[0].usVddgfxLimit
;
364 static int get_mclk_voltage_dependency_table(
365 struct pp_hwmgr
*hwmgr
,
366 phm_ppt_v1_clock_voltage_dependency_table
**pp_tonga_mclk_dep_table
,
367 const ATOM_Tonga_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((0 != mclk_dep_table
->ucNumEntries
),
374 "Invalid PowerPlay Table!", return -1);
376 table_size
= sizeof(uint32_t) + sizeof(phm_ppt_v1_clock_voltage_dependency_record
)
377 * mclk_dep_table
->ucNumEntries
;
379 mclk_table
= kzalloc(table_size
, GFP_KERNEL
);
381 if (NULL
== mclk_table
)
384 memset(mclk_table
, 0x00, table_size
);
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
].ucVddcInd
;
391 mclk_table
->entries
[i
].vdd_offset
=
392 mclk_dep_table
->entries
[i
].usVddgfxOffset
;
393 mclk_table
->entries
[i
].vddci
=
394 mclk_dep_table
->entries
[i
].usVddci
;
395 mclk_table
->entries
[i
].mvdd
=
396 mclk_dep_table
->entries
[i
].usMvdd
;
397 mclk_table
->entries
[i
].clk
=
398 mclk_dep_table
->entries
[i
].ulMclk
;
401 *pp_tonga_mclk_dep_table
= mclk_table
;
406 static int get_sclk_voltage_dependency_table(
407 struct pp_hwmgr
*hwmgr
,
408 phm_ppt_v1_clock_voltage_dependency_table
**pp_tonga_sclk_dep_table
,
409 const PPTable_Generic_SubTable_Header
*sclk_dep_table
412 uint32_t table_size
, i
;
413 phm_ppt_v1_clock_voltage_dependency_table
*sclk_table
;
415 if (sclk_dep_table
->ucRevId
< 1) {
416 const ATOM_Tonga_SCLK_Dependency_Table
*tonga_table
=
417 (ATOM_Tonga_SCLK_Dependency_Table
*)sclk_dep_table
;
419 PP_ASSERT_WITH_CODE((0 != tonga_table
->ucNumEntries
),
420 "Invalid PowerPlay Table!", return -1);
422 table_size
= sizeof(uint32_t) + sizeof(phm_ppt_v1_clock_voltage_dependency_record
)
423 * tonga_table
->ucNumEntries
;
425 sclk_table
= kzalloc(table_size
, GFP_KERNEL
);
427 if (NULL
== sclk_table
)
430 memset(sclk_table
, 0x00, table_size
);
432 sclk_table
->count
= (uint32_t)tonga_table
->ucNumEntries
;
434 for (i
= 0; i
< tonga_table
->ucNumEntries
; i
++) {
435 sclk_table
->entries
[i
].vddInd
=
436 tonga_table
->entries
[i
].ucVddInd
;
437 sclk_table
->entries
[i
].vdd_offset
=
438 tonga_table
->entries
[i
].usVddcOffset
;
439 sclk_table
->entries
[i
].clk
=
440 tonga_table
->entries
[i
].ulSclk
;
441 sclk_table
->entries
[i
].cks_enable
=
442 (((tonga_table
->entries
[i
].ucCKSVOffsetandDisable
& 0x80) >> 7) == 0) ? 1 : 0;
443 sclk_table
->entries
[i
].cks_voffset
=
444 (tonga_table
->entries
[i
].ucCKSVOffsetandDisable
& 0x7F);
447 const ATOM_Polaris_SCLK_Dependency_Table
*polaris_table
=
448 (ATOM_Polaris_SCLK_Dependency_Table
*)sclk_dep_table
;
450 PP_ASSERT_WITH_CODE((0 != polaris_table
->ucNumEntries
),
451 "Invalid PowerPlay Table!", return -1);
453 table_size
= sizeof(uint32_t) + sizeof(phm_ppt_v1_clock_voltage_dependency_record
)
454 * polaris_table
->ucNumEntries
;
456 sclk_table
= kzalloc(table_size
, GFP_KERNEL
);
458 if (NULL
== sclk_table
)
461 memset(sclk_table
, 0x00, table_size
);
463 sclk_table
->count
= (uint32_t)polaris_table
->ucNumEntries
;
465 for (i
= 0; i
< polaris_table
->ucNumEntries
; i
++) {
466 sclk_table
->entries
[i
].vddInd
=
467 polaris_table
->entries
[i
].ucVddInd
;
468 sclk_table
->entries
[i
].vdd_offset
=
469 polaris_table
->entries
[i
].usVddcOffset
;
470 sclk_table
->entries
[i
].clk
=
471 polaris_table
->entries
[i
].ulSclk
;
472 sclk_table
->entries
[i
].cks_enable
=
473 (((polaris_table
->entries
[i
].ucCKSVOffsetandDisable
& 0x80) >> 7) == 0) ? 1 : 0;
474 sclk_table
->entries
[i
].cks_voffset
=
475 (polaris_table
->entries
[i
].ucCKSVOffsetandDisable
& 0x7F);
476 sclk_table
->entries
[i
].sclk_offset
= polaris_table
->entries
[i
].ulSclkOffset
;
479 *pp_tonga_sclk_dep_table
= sclk_table
;
484 static int get_pcie_table(
485 struct pp_hwmgr
*hwmgr
,
486 phm_ppt_v1_pcie_table
**pp_tonga_pcie_table
,
487 const PPTable_Generic_SubTable_Header
* pTable
490 uint32_t table_size
, i
, pcie_count
;
491 phm_ppt_v1_pcie_table
*pcie_table
;
492 struct phm_ppt_v1_information
*pp_table_information
=
493 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
495 if (pTable
->ucRevId
< 1) {
496 const ATOM_Tonga_PCIE_Table
*atom_pcie_table
= (ATOM_Tonga_PCIE_Table
*)pTable
;
497 PP_ASSERT_WITH_CODE((atom_pcie_table
->ucNumEntries
!= 0),
498 "Invalid PowerPlay Table!", return -1);
500 table_size
= sizeof(uint32_t) +
501 sizeof(phm_ppt_v1_pcie_record
) * atom_pcie_table
->ucNumEntries
;
503 pcie_table
= kzalloc(table_size
, GFP_KERNEL
);
505 if (pcie_table
== NULL
)
508 memset(pcie_table
, 0x00, table_size
);
511 * Make sure the number of pcie entries are less than or equal to sclk dpm levels.
512 * Since first PCIE entry is for ULV, #pcie has to be <= SclkLevel + 1.
514 pcie_count
= (pp_table_information
->vdd_dep_on_sclk
->count
) + 1;
515 if ((uint32_t)atom_pcie_table
->ucNumEntries
<= pcie_count
)
516 pcie_count
= (uint32_t)atom_pcie_table
->ucNumEntries
;
518 printk(KERN_ERR
"[ powerplay ] Number of Pcie Entries exceed the number of SCLK Dpm Levels! \
519 Disregarding the excess entries... \n");
521 pcie_table
->count
= pcie_count
;
523 for (i
= 0; i
< pcie_count
; i
++) {
524 pcie_table
->entries
[i
].gen_speed
=
525 atom_pcie_table
->entries
[i
].ucPCIEGenSpeed
;
526 pcie_table
->entries
[i
].lane_width
=
527 atom_pcie_table
->entries
[i
].usPCIELaneWidth
;
530 *pp_tonga_pcie_table
= pcie_table
;
532 /* Polaris10/Polaris11 and newer. */
533 const ATOM_Polaris10_PCIE_Table
*atom_pcie_table
= (ATOM_Polaris10_PCIE_Table
*)pTable
;
534 PP_ASSERT_WITH_CODE((atom_pcie_table
->ucNumEntries
!= 0),
535 "Invalid PowerPlay Table!", return -1);
537 table_size
= sizeof(uint32_t) +
538 sizeof(phm_ppt_v1_pcie_record
) * atom_pcie_table
->ucNumEntries
;
540 pcie_table
= kzalloc(table_size
, GFP_KERNEL
);
542 if (pcie_table
== NULL
)
545 memset(pcie_table
, 0x00, table_size
);
548 * Make sure the number of pcie entries are less than or equal to sclk dpm levels.
549 * Since first PCIE entry is for ULV, #pcie has to be <= SclkLevel + 1.
551 pcie_count
= (pp_table_information
->vdd_dep_on_sclk
->count
) + 1;
552 if ((uint32_t)atom_pcie_table
->ucNumEntries
<= pcie_count
)
553 pcie_count
= (uint32_t)atom_pcie_table
->ucNumEntries
;
555 printk(KERN_ERR
"[ powerplay ] Number of Pcie Entries exceed the number of SCLK Dpm Levels! \
556 Disregarding the excess entries... \n");
558 pcie_table
->count
= pcie_count
;
560 for (i
= 0; i
< pcie_count
; i
++) {
561 pcie_table
->entries
[i
].gen_speed
=
562 atom_pcie_table
->entries
[i
].ucPCIEGenSpeed
;
563 pcie_table
->entries
[i
].lane_width
=
564 atom_pcie_table
->entries
[i
].usPCIELaneWidth
;
565 pcie_table
->entries
[i
].pcie_sclk
=
566 atom_pcie_table
->entries
[i
].ulPCIE_Sclk
;
569 *pp_tonga_pcie_table
= pcie_table
;
575 static int get_cac_tdp_table(
576 struct pp_hwmgr
*hwmgr
,
577 struct phm_cac_tdp_table
**cac_tdp_table
,
578 const PPTable_Generic_SubTable_Header
* table
582 struct phm_cac_tdp_table
*tdp_table
;
584 table_size
= sizeof(uint32_t) + sizeof(struct phm_cac_tdp_table
);
585 tdp_table
= kzalloc(table_size
, GFP_KERNEL
);
587 if (NULL
== tdp_table
)
590 memset(tdp_table
, 0x00, table_size
);
592 hwmgr
->dyn_state
.cac_dtp_table
= kzalloc(table_size
, GFP_KERNEL
);
594 if (NULL
== hwmgr
->dyn_state
.cac_dtp_table
) {
599 memset(hwmgr
->dyn_state
.cac_dtp_table
, 0x00, table_size
);
601 if (table
->ucRevId
< 3) {
602 const ATOM_Tonga_PowerTune_Table
*tonga_table
=
603 (ATOM_Tonga_PowerTune_Table
*)table
;
604 tdp_table
->usTDP
= tonga_table
->usTDP
;
605 tdp_table
->usConfigurableTDP
=
606 tonga_table
->usConfigurableTDP
;
607 tdp_table
->usTDC
= tonga_table
->usTDC
;
608 tdp_table
->usBatteryPowerLimit
=
609 tonga_table
->usBatteryPowerLimit
;
610 tdp_table
->usSmallPowerLimit
=
611 tonga_table
->usSmallPowerLimit
;
612 tdp_table
->usLowCACLeakage
=
613 tonga_table
->usLowCACLeakage
;
614 tdp_table
->usHighCACLeakage
=
615 tonga_table
->usHighCACLeakage
;
616 tdp_table
->usMaximumPowerDeliveryLimit
=
617 tonga_table
->usMaximumPowerDeliveryLimit
;
618 tdp_table
->usDefaultTargetOperatingTemp
=
619 tonga_table
->usTjMax
;
620 tdp_table
->usTargetOperatingTemp
=
621 tonga_table
->usTjMax
; /*Set the initial temp to the same as default */
622 tdp_table
->usPowerTuneDataSetID
=
623 tonga_table
->usPowerTuneDataSetID
;
624 tdp_table
->usSoftwareShutdownTemp
=
625 tonga_table
->usSoftwareShutdownTemp
;
626 tdp_table
->usClockStretchAmount
=
627 tonga_table
->usClockStretchAmount
;
628 } else { /* Fiji and newer */
629 const ATOM_Fiji_PowerTune_Table
*fijitable
=
630 (ATOM_Fiji_PowerTune_Table
*)table
;
631 tdp_table
->usTDP
= fijitable
->usTDP
;
632 tdp_table
->usConfigurableTDP
= fijitable
->usConfigurableTDP
;
633 tdp_table
->usTDC
= fijitable
->usTDC
;
634 tdp_table
->usBatteryPowerLimit
= fijitable
->usBatteryPowerLimit
;
635 tdp_table
->usSmallPowerLimit
= fijitable
->usSmallPowerLimit
;
636 tdp_table
->usLowCACLeakage
= fijitable
->usLowCACLeakage
;
637 tdp_table
->usHighCACLeakage
= fijitable
->usHighCACLeakage
;
638 tdp_table
->usMaximumPowerDeliveryLimit
=
639 fijitable
->usMaximumPowerDeliveryLimit
;
640 tdp_table
->usDefaultTargetOperatingTemp
=
642 tdp_table
->usTargetOperatingTemp
=
643 fijitable
->usTjMax
; /*Set the initial temp to the same as default */
644 tdp_table
->usPowerTuneDataSetID
=
645 fijitable
->usPowerTuneDataSetID
;
646 tdp_table
->usSoftwareShutdownTemp
=
647 fijitable
->usSoftwareShutdownTemp
;
648 tdp_table
->usClockStretchAmount
=
649 fijitable
->usClockStretchAmount
;
650 tdp_table
->usTemperatureLimitHotspot
=
651 fijitable
->usTemperatureLimitHotspot
;
652 tdp_table
->usTemperatureLimitLiquid1
=
653 fijitable
->usTemperatureLimitLiquid1
;
654 tdp_table
->usTemperatureLimitLiquid2
=
655 fijitable
->usTemperatureLimitLiquid2
;
656 tdp_table
->usTemperatureLimitVrVddc
=
657 fijitable
->usTemperatureLimitVrVddc
;
658 tdp_table
->usTemperatureLimitVrMvdd
=
659 fijitable
->usTemperatureLimitVrMvdd
;
660 tdp_table
->usTemperatureLimitPlx
=
661 fijitable
->usTemperatureLimitPlx
;
662 tdp_table
->ucLiquid1_I2C_address
=
663 fijitable
->ucLiquid1_I2C_address
;
664 tdp_table
->ucLiquid2_I2C_address
=
665 fijitable
->ucLiquid2_I2C_address
;
666 tdp_table
->ucLiquid_I2C_Line
=
667 fijitable
->ucLiquid_I2C_Line
;
668 tdp_table
->ucVr_I2C_address
= fijitable
->ucVr_I2C_address
;
669 tdp_table
->ucVr_I2C_Line
= fijitable
->ucVr_I2C_Line
;
670 tdp_table
->ucPlx_I2C_address
= fijitable
->ucPlx_I2C_address
;
671 tdp_table
->ucPlx_I2C_Line
= fijitable
->ucPlx_I2C_Line
;
674 *cac_tdp_table
= tdp_table
;
679 static int get_mm_clock_voltage_table(
680 struct pp_hwmgr
*hwmgr
,
681 phm_ppt_v1_mm_clock_voltage_dependency_table
**tonga_mm_table
,
682 const ATOM_Tonga_MM_Dependency_Table
* mm_dependency_table
685 uint32_t table_size
, i
;
686 const ATOM_Tonga_MM_Dependency_Record
*mm_dependency_record
;
687 phm_ppt_v1_mm_clock_voltage_dependency_table
*mm_table
;
689 PP_ASSERT_WITH_CODE((0 != mm_dependency_table
->ucNumEntries
),
690 "Invalid PowerPlay Table!", return -1);
691 table_size
= sizeof(uint32_t) +
692 sizeof(phm_ppt_v1_mm_clock_voltage_dependency_record
)
693 * mm_dependency_table
->ucNumEntries
;
694 mm_table
= kzalloc(table_size
, GFP_KERNEL
);
696 if (NULL
== mm_table
)
699 memset(mm_table
, 0x00, table_size
);
701 mm_table
->count
= mm_dependency_table
->ucNumEntries
;
703 for (i
= 0; i
< mm_dependency_table
->ucNumEntries
; i
++) {
704 mm_dependency_record
= &mm_dependency_table
->entries
[i
];
705 mm_table
->entries
[i
].vddcInd
= mm_dependency_record
->ucVddcInd
;
706 mm_table
->entries
[i
].vddgfx_offset
= mm_dependency_record
->usVddgfxOffset
;
707 mm_table
->entries
[i
].aclk
= mm_dependency_record
->ulAClk
;
708 mm_table
->entries
[i
].samclock
= mm_dependency_record
->ulSAMUClk
;
709 mm_table
->entries
[i
].eclk
= mm_dependency_record
->ulEClk
;
710 mm_table
->entries
[i
].vclk
= mm_dependency_record
->ulVClk
;
711 mm_table
->entries
[i
].dclk
= mm_dependency_record
->ulDClk
;
714 *tonga_mm_table
= mm_table
;
720 * Private Function used during initialization.
721 * Initialize clock voltage dependency
722 * @param hwmgr Pointer to the hardware manager.
723 * @param powerplay_table Pointer to the PowerPlay Table.
725 static int init_clock_voltage_dependency(
726 struct pp_hwmgr
*hwmgr
,
727 const ATOM_Tonga_POWERPLAYTABLE
*powerplay_table
731 struct phm_ppt_v1_information
*pp_table_information
=
732 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
734 const ATOM_Tonga_MM_Dependency_Table
*mm_dependency_table
=
735 (const ATOM_Tonga_MM_Dependency_Table
*)(((unsigned long) powerplay_table
) +
736 le16_to_cpu(powerplay_table
->usMMDependencyTableOffset
));
737 const PPTable_Generic_SubTable_Header
*pPowerTuneTable
=
738 (const PPTable_Generic_SubTable_Header
*)(((unsigned long) powerplay_table
) +
739 le16_to_cpu(powerplay_table
->usPowerTuneTableOffset
));
740 const ATOM_Tonga_MCLK_Dependency_Table
*mclk_dep_table
=
741 (const ATOM_Tonga_MCLK_Dependency_Table
*)(((unsigned long) powerplay_table
) +
742 le16_to_cpu(powerplay_table
->usMclkDependencyTableOffset
));
743 const PPTable_Generic_SubTable_Header
*sclk_dep_table
=
744 (const PPTable_Generic_SubTable_Header
*)(((unsigned long) powerplay_table
) +
745 le16_to_cpu(powerplay_table
->usSclkDependencyTableOffset
));
746 const ATOM_Tonga_Hard_Limit_Table
*pHardLimits
=
747 (const ATOM_Tonga_Hard_Limit_Table
*)(((unsigned long) powerplay_table
) +
748 le16_to_cpu(powerplay_table
->usHardLimitTableOffset
));
749 const PPTable_Generic_SubTable_Header
*pcie_table
=
750 (const PPTable_Generic_SubTable_Header
*)(((unsigned long) powerplay_table
) +
751 le16_to_cpu(powerplay_table
->usPCIETableOffset
));
753 pp_table_information
->vdd_dep_on_sclk
= NULL
;
754 pp_table_information
->vdd_dep_on_mclk
= NULL
;
755 pp_table_information
->mm_dep_table
= NULL
;
756 pp_table_information
->pcie_table
= NULL
;
758 if (powerplay_table
->usMMDependencyTableOffset
!= 0)
759 result
= get_mm_clock_voltage_table(hwmgr
,
760 &pp_table_information
->mm_dep_table
, mm_dependency_table
);
762 if (result
== 0 && powerplay_table
->usPowerTuneTableOffset
!= 0)
763 result
= get_cac_tdp_table(hwmgr
,
764 &pp_table_information
->cac_dtp_table
, pPowerTuneTable
);
766 if (result
== 0 && powerplay_table
->usSclkDependencyTableOffset
!= 0)
767 result
= get_sclk_voltage_dependency_table(hwmgr
,
768 &pp_table_information
->vdd_dep_on_sclk
, sclk_dep_table
);
770 if (result
== 0 && powerplay_table
->usMclkDependencyTableOffset
!= 0)
771 result
= get_mclk_voltage_dependency_table(hwmgr
,
772 &pp_table_information
->vdd_dep_on_mclk
, mclk_dep_table
);
774 if (result
== 0 && powerplay_table
->usPCIETableOffset
!= 0)
775 result
= get_pcie_table(hwmgr
,
776 &pp_table_information
->pcie_table
, pcie_table
);
778 if (result
== 0 && powerplay_table
->usHardLimitTableOffset
!= 0)
779 result
= get_hard_limits(hwmgr
,
780 &pp_table_information
->max_clock_voltage_on_dc
, pHardLimits
);
782 hwmgr
->dyn_state
.max_clock_voltage_on_dc
.sclk
=
783 pp_table_information
->max_clock_voltage_on_dc
.sclk
;
784 hwmgr
->dyn_state
.max_clock_voltage_on_dc
.mclk
=
785 pp_table_information
->max_clock_voltage_on_dc
.mclk
;
786 hwmgr
->dyn_state
.max_clock_voltage_on_dc
.vddc
=
787 pp_table_information
->max_clock_voltage_on_dc
.vddc
;
788 hwmgr
->dyn_state
.max_clock_voltage_on_dc
.vddci
=
789 pp_table_information
->max_clock_voltage_on_dc
.vddci
;
791 if (result
== 0 && (NULL
!= pp_table_information
->vdd_dep_on_mclk
)
792 && (0 != pp_table_information
->vdd_dep_on_mclk
->count
))
793 result
= get_valid_clk(hwmgr
, &pp_table_information
->valid_mclk_values
,
794 pp_table_information
->vdd_dep_on_mclk
);
796 if (result
== 0 && (NULL
!= pp_table_information
->vdd_dep_on_sclk
)
797 && (0 != pp_table_information
->vdd_dep_on_sclk
->count
))
798 result
= get_valid_clk(hwmgr
, &pp_table_information
->valid_sclk_values
,
799 pp_table_information
->vdd_dep_on_sclk
);
804 /** Retrieves the (signed) Overdrive limits from VBIOS.
805 * The max engine clock, memory clock and max temperature come from the firmware info table.
807 * The information is placed into the platform descriptor.
809 * @param hwmgr source of the VBIOS table and owner of the platform descriptor to be updated.
810 * @param powerplay_table the address of the PowerPlay table.
812 * @return 1 as long as the firmware info table was present and of a supported version.
814 static int init_over_drive_limits(
815 struct pp_hwmgr
*hwmgr
,
816 const ATOM_Tonga_POWERPLAYTABLE
*powerplay_table
)
818 hwmgr
->platform_descriptor
.overdriveLimit
.engineClock
=
819 le16_to_cpu(powerplay_table
->ulMaxODEngineClock
);
820 hwmgr
->platform_descriptor
.overdriveLimit
.memoryClock
=
821 le16_to_cpu(powerplay_table
->ulMaxODMemoryClock
);
823 hwmgr
->platform_descriptor
.minOverdriveVDDC
= 0;
824 hwmgr
->platform_descriptor
.maxOverdriveVDDC
= 0;
825 hwmgr
->platform_descriptor
.overdriveVDDCStep
= 0;
827 if (hwmgr
->platform_descriptor
.overdriveLimit
.engineClock
> 0 \
828 && hwmgr
->platform_descriptor
.overdriveLimit
.memoryClock
> 0) {
829 phm_cap_set(hwmgr
->platform_descriptor
.platformCaps
,
830 PHM_PlatformCaps_ACOverdriveSupport
);
837 * Private Function used during initialization.
838 * Inspect the PowerPlay table for obvious signs of corruption.
839 * @param hwmgr Pointer to the hardware manager.
840 * @param powerplay_table Pointer to the PowerPlay Table.
841 * @exception This implementation always returns 1.
843 static int init_thermal_controller(
844 struct pp_hwmgr
*hwmgr
,
845 const ATOM_Tonga_POWERPLAYTABLE
*powerplay_table
848 const PPTable_Generic_SubTable_Header
*fan_table
;
849 ATOM_Tonga_Thermal_Controller
*thermal_controller
;
851 thermal_controller
= (ATOM_Tonga_Thermal_Controller
*)
852 (((unsigned long)powerplay_table
) +
853 le16_to_cpu(powerplay_table
->usThermalControllerOffset
));
854 PP_ASSERT_WITH_CODE((0 != powerplay_table
->usThermalControllerOffset
),
855 "Thermal controller table not set!", return -1);
857 hwmgr
->thermal_controller
.ucType
= thermal_controller
->ucType
;
858 hwmgr
->thermal_controller
.ucI2cLine
= thermal_controller
->ucI2cLine
;
859 hwmgr
->thermal_controller
.ucI2cAddress
= thermal_controller
->ucI2cAddress
;
861 hwmgr
->thermal_controller
.fanInfo
.bNoFan
=
862 (0 != (thermal_controller
->ucFanParameters
& ATOM_TONGA_PP_FANPARAMETERS_NOFAN
));
864 hwmgr
->thermal_controller
.fanInfo
.ucTachometerPulsesPerRevolution
=
865 thermal_controller
->ucFanParameters
&
866 ATOM_TONGA_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK
;
868 hwmgr
->thermal_controller
.fanInfo
.ulMinRPM
869 = thermal_controller
->ucFanMinRPM
* 100UL;
870 hwmgr
->thermal_controller
.fanInfo
.ulMaxRPM
871 = thermal_controller
->ucFanMaxRPM
* 100UL;
875 ATOM_TONGA_PP_THERMALCONTROLLER_NONE
!= hwmgr
->thermal_controller
.ucType
,
876 PHM_PlatformCaps_ThermalController
879 if (0 == powerplay_table
->usFanTableOffset
)
882 fan_table
= (const PPTable_Generic_SubTable_Header
*)
883 (((unsigned long)powerplay_table
) +
884 le16_to_cpu(powerplay_table
->usFanTableOffset
));
886 PP_ASSERT_WITH_CODE((0 != powerplay_table
->usFanTableOffset
),
887 "Fan table not set!", return -1);
888 PP_ASSERT_WITH_CODE((0 < fan_table
->ucRevId
),
889 "Unsupported fan table format!", return -1);
891 hwmgr
->thermal_controller
.advanceFanControlParameters
.ulCycleDelay
893 phm_cap_set(hwmgr
->platform_descriptor
.platformCaps
,
894 PHM_PlatformCaps_MicrocodeFanControl
);
896 if (fan_table
->ucRevId
< 8) {
897 const ATOM_Tonga_Fan_Table
*tonga_fan_table
=
898 (ATOM_Tonga_Fan_Table
*)fan_table
;
899 hwmgr
->thermal_controller
.advanceFanControlParameters
.ucTHyst
900 = tonga_fan_table
->ucTHyst
;
901 hwmgr
->thermal_controller
.advanceFanControlParameters
.usTMin
902 = tonga_fan_table
->usTMin
;
903 hwmgr
->thermal_controller
.advanceFanControlParameters
.usTMed
904 = tonga_fan_table
->usTMed
;
905 hwmgr
->thermal_controller
.advanceFanControlParameters
.usTHigh
906 = tonga_fan_table
->usTHigh
;
907 hwmgr
->thermal_controller
.advanceFanControlParameters
.usPWMMin
908 = tonga_fan_table
->usPWMMin
;
909 hwmgr
->thermal_controller
.advanceFanControlParameters
.usPWMMed
910 = tonga_fan_table
->usPWMMed
;
911 hwmgr
->thermal_controller
.advanceFanControlParameters
.usPWMHigh
912 = tonga_fan_table
->usPWMHigh
;
913 hwmgr
->thermal_controller
.advanceFanControlParameters
.usTMax
914 = 10900; /* hard coded */
915 hwmgr
->thermal_controller
.advanceFanControlParameters
.usTMax
916 = tonga_fan_table
->usTMax
;
917 hwmgr
->thermal_controller
.advanceFanControlParameters
.ucFanControlMode
918 = tonga_fan_table
->ucFanControlMode
;
919 hwmgr
->thermal_controller
.advanceFanControlParameters
.usDefaultMaxFanPWM
920 = tonga_fan_table
->usFanPWMMax
;
921 hwmgr
->thermal_controller
.advanceFanControlParameters
.usDefaultFanOutputSensitivity
923 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanOutputSensitivity
924 = tonga_fan_table
->usFanOutputSensitivity
;
925 hwmgr
->thermal_controller
.advanceFanControlParameters
.usDefaultMaxFanRPM
926 = tonga_fan_table
->usFanRPMMax
;
927 hwmgr
->thermal_controller
.advanceFanControlParameters
.ulMinFanSCLKAcousticLimit
928 = (tonga_fan_table
->ulMinFanSCLKAcousticLimit
/ 100); /* PPTable stores it in 10Khz unit for 2 decimal places. SMC wants MHz. */
929 hwmgr
->thermal_controller
.advanceFanControlParameters
.ucTargetTemperature
930 = tonga_fan_table
->ucTargetTemperature
;
931 hwmgr
->thermal_controller
.advanceFanControlParameters
.ucMinimumPWMLimit
932 = tonga_fan_table
->ucMinimumPWMLimit
;
934 const ATOM_Fiji_Fan_Table
*fiji_fan_table
=
935 (ATOM_Fiji_Fan_Table
*)fan_table
;
936 hwmgr
->thermal_controller
.advanceFanControlParameters
.ucTHyst
937 = fiji_fan_table
->ucTHyst
;
938 hwmgr
->thermal_controller
.advanceFanControlParameters
.usTMin
939 = fiji_fan_table
->usTMin
;
940 hwmgr
->thermal_controller
.advanceFanControlParameters
.usTMed
941 = fiji_fan_table
->usTMed
;
942 hwmgr
->thermal_controller
.advanceFanControlParameters
.usTHigh
943 = fiji_fan_table
->usTHigh
;
944 hwmgr
->thermal_controller
.advanceFanControlParameters
.usPWMMin
945 = fiji_fan_table
->usPWMMin
;
946 hwmgr
->thermal_controller
.advanceFanControlParameters
.usPWMMed
947 = fiji_fan_table
->usPWMMed
;
948 hwmgr
->thermal_controller
.advanceFanControlParameters
.usPWMHigh
949 = fiji_fan_table
->usPWMHigh
;
950 hwmgr
->thermal_controller
.advanceFanControlParameters
.usTMax
951 = fiji_fan_table
->usTMax
;
952 hwmgr
->thermal_controller
.advanceFanControlParameters
.ucFanControlMode
953 = fiji_fan_table
->ucFanControlMode
;
954 hwmgr
->thermal_controller
.advanceFanControlParameters
.usDefaultMaxFanPWM
955 = fiji_fan_table
->usFanPWMMax
;
956 hwmgr
->thermal_controller
.advanceFanControlParameters
.usDefaultFanOutputSensitivity
958 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanOutputSensitivity
959 = fiji_fan_table
->usFanOutputSensitivity
;
960 hwmgr
->thermal_controller
.advanceFanControlParameters
.usDefaultMaxFanRPM
961 = fiji_fan_table
->usFanRPMMax
;
962 hwmgr
->thermal_controller
.advanceFanControlParameters
.ulMinFanSCLKAcousticLimit
963 = (fiji_fan_table
->ulMinFanSCLKAcousticLimit
/ 100); /* PPTable stores it in 10Khz unit for 2 decimal places. SMC wants MHz. */
964 hwmgr
->thermal_controller
.advanceFanControlParameters
.ucTargetTemperature
965 = fiji_fan_table
->ucTargetTemperature
;
966 hwmgr
->thermal_controller
.advanceFanControlParameters
.ucMinimumPWMLimit
967 = fiji_fan_table
->ucMinimumPWMLimit
;
969 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanGainEdge
970 = fiji_fan_table
->usFanGainEdge
;
971 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanGainHotspot
972 = fiji_fan_table
->usFanGainHotspot
;
973 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanGainLiquid
974 = fiji_fan_table
->usFanGainLiquid
;
975 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanGainVrVddc
976 = fiji_fan_table
->usFanGainVrVddc
;
977 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanGainVrMvdd
978 = fiji_fan_table
->usFanGainVrMvdd
;
979 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanGainPlx
980 = fiji_fan_table
->usFanGainPlx
;
981 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanGainHbm
982 = fiji_fan_table
->usFanGainHbm
;
989 * Private Function used during initialization.
990 * Inspect the PowerPlay table for obvious signs of corruption.
991 * @param hwmgr Pointer to the hardware manager.
992 * @param powerplay_table Pointer to the PowerPlay Table.
993 * @exception 2 if the powerplay table is incorrect.
995 static int check_powerplay_tables(
996 struct pp_hwmgr
*hwmgr
,
997 const ATOM_Tonga_POWERPLAYTABLE
*powerplay_table
1000 const ATOM_Tonga_State_Array
*state_arrays
;
1002 state_arrays
= (ATOM_Tonga_State_Array
*)(((unsigned long)powerplay_table
) +
1003 le16_to_cpu(powerplay_table
->usStateArrayOffset
));
1005 PP_ASSERT_WITH_CODE((ATOM_Tonga_TABLE_REVISION_TONGA
<=
1006 powerplay_table
->sHeader
.ucTableFormatRevision
),
1007 "Unsupported PPTable format!", return -1);
1008 PP_ASSERT_WITH_CODE((0 != powerplay_table
->usStateArrayOffset
),
1009 "State table is not set!", return -1);
1010 PP_ASSERT_WITH_CODE((0 < powerplay_table
->sHeader
.usStructureSize
),
1011 "Invalid PowerPlay Table!", return -1);
1012 PP_ASSERT_WITH_CODE((0 < state_arrays
->ucNumEntries
),
1013 "Invalid PowerPlay Table!", return -1);
1018 int tonga_pp_tables_initialize(struct pp_hwmgr
*hwmgr
)
1021 const ATOM_Tonga_POWERPLAYTABLE
*powerplay_table
;
1023 hwmgr
->pptable
= kzalloc(sizeof(struct phm_ppt_v1_information
), GFP_KERNEL
);
1025 PP_ASSERT_WITH_CODE((NULL
!= hwmgr
->pptable
),
1026 "Failed to allocate hwmgr->pptable!", return -ENOMEM
);
1028 memset(hwmgr
->pptable
, 0x00, sizeof(struct phm_ppt_v1_information
));
1030 powerplay_table
= get_powerplay_table(hwmgr
);
1032 PP_ASSERT_WITH_CODE((NULL
!= powerplay_table
),
1033 "Missing PowerPlay Table!", return -1);
1035 result
= check_powerplay_tables(hwmgr
, powerplay_table
);
1037 PP_ASSERT_WITH_CODE((result
== 0),
1038 "check_powerplay_tables failed", return result
);
1040 result
= set_platform_caps(hwmgr
,
1041 le32_to_cpu(powerplay_table
->ulPlatformCaps
));
1043 PP_ASSERT_WITH_CODE((result
== 0),
1044 "set_platform_caps failed", return result
);
1046 result
= init_thermal_controller(hwmgr
, powerplay_table
);
1048 PP_ASSERT_WITH_CODE((result
== 0),
1049 "init_thermal_controller failed", return result
);
1051 result
= init_over_drive_limits(hwmgr
, powerplay_table
);
1053 PP_ASSERT_WITH_CODE((result
== 0),
1054 "init_over_drive_limits failed", return result
);
1056 result
= init_clock_voltage_dependency(hwmgr
, powerplay_table
);
1058 PP_ASSERT_WITH_CODE((result
== 0),
1059 "init_clock_voltage_dependency failed", return result
);
1061 result
= init_dpm_2_parameters(hwmgr
, powerplay_table
);
1063 PP_ASSERT_WITH_CODE((result
== 0),
1064 "init_dpm_2_parameters failed", return result
);
1069 int tonga_pp_tables_uninitialize(struct pp_hwmgr
*hwmgr
)
1071 struct phm_ppt_v1_information
*pp_table_information
=
1072 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
1074 kfree(pp_table_information
->vdd_dep_on_sclk
);
1075 pp_table_information
->vdd_dep_on_sclk
= NULL
;
1077 kfree(pp_table_information
->vdd_dep_on_mclk
);
1078 pp_table_information
->vdd_dep_on_mclk
= NULL
;
1080 kfree(pp_table_information
->valid_mclk_values
);
1081 pp_table_information
->valid_mclk_values
= NULL
;
1083 kfree(pp_table_information
->valid_sclk_values
);
1084 pp_table_information
->valid_sclk_values
= NULL
;
1086 kfree(pp_table_information
->vddc_lookup_table
);
1087 pp_table_information
->vddc_lookup_table
= NULL
;
1089 kfree(pp_table_information
->vddgfx_lookup_table
);
1090 pp_table_information
->vddgfx_lookup_table
= NULL
;
1092 kfree(pp_table_information
->mm_dep_table
);
1093 pp_table_information
->mm_dep_table
= NULL
;
1095 kfree(pp_table_information
->cac_dtp_table
);
1096 pp_table_information
->cac_dtp_table
= NULL
;
1098 kfree(hwmgr
->dyn_state
.cac_dtp_table
);
1099 hwmgr
->dyn_state
.cac_dtp_table
= NULL
;
1101 kfree(pp_table_information
->ppm_parameter_table
);
1102 pp_table_information
->ppm_parameter_table
= NULL
;
1104 kfree(pp_table_information
->pcie_table
);
1105 pp_table_information
->pcie_table
= NULL
;
1107 kfree(hwmgr
->pptable
);
1108 hwmgr
->pptable
= NULL
;
1113 const struct pp_table_func tonga_pptable_funcs
= {
1114 .pptable_init
= tonga_pp_tables_initialize
,
1115 .pptable_fini
= tonga_pp_tables_uninitialize
,
1118 int tonga_get_number_of_powerplay_table_entries(struct pp_hwmgr
*hwmgr
)
1120 const ATOM_Tonga_State_Array
* state_arrays
;
1121 const ATOM_Tonga_POWERPLAYTABLE
*pp_table
= get_powerplay_table(hwmgr
);
1123 PP_ASSERT_WITH_CODE((NULL
!= pp_table
),
1124 "Missing PowerPlay Table!", return -1);
1125 PP_ASSERT_WITH_CODE((pp_table
->sHeader
.ucTableFormatRevision
>=
1126 ATOM_Tonga_TABLE_REVISION_TONGA
),
1127 "Incorrect PowerPlay table revision!", return -1);
1129 state_arrays
= (ATOM_Tonga_State_Array
*)(((unsigned long)pp_table
) +
1130 le16_to_cpu(pp_table
->usStateArrayOffset
));
1132 return (uint32_t)(state_arrays
->ucNumEntries
);
1136 * Private function to convert flags stored in the BIOS to software flags in PowerPlay.
1138 static uint32_t make_classification_flags(struct pp_hwmgr
*hwmgr
,
1139 uint16_t classification
, uint16_t classification2
)
1141 uint32_t result
= 0;
1143 if (classification
& ATOM_PPLIB_CLASSIFICATION_BOOT
)
1144 result
|= PP_StateClassificationFlag_Boot
;
1146 if (classification
& ATOM_PPLIB_CLASSIFICATION_THERMAL
)
1147 result
|= PP_StateClassificationFlag_Thermal
;
1149 if (classification
& ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE
)
1150 result
|= PP_StateClassificationFlag_LimitedPowerSource
;
1152 if (classification
& ATOM_PPLIB_CLASSIFICATION_REST
)
1153 result
|= PP_StateClassificationFlag_Rest
;
1155 if (classification
& ATOM_PPLIB_CLASSIFICATION_FORCED
)
1156 result
|= PP_StateClassificationFlag_Forced
;
1158 if (classification
& ATOM_PPLIB_CLASSIFICATION_ACPI
)
1159 result
|= PP_StateClassificationFlag_ACPI
;
1161 if (classification2
& ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2
)
1162 result
|= PP_StateClassificationFlag_LimitedPowerSource_2
;
1168 * Create a Power State out of an entry in the PowerPlay table.
1169 * This function is called by the hardware back-end.
1170 * @param hwmgr Pointer to the hardware manager.
1171 * @param entry_index The index of the entry to be extracted from the table.
1172 * @param power_state The address of the PowerState instance being created.
1173 * @return -1 if the entry cannot be retrieved.
1175 int tonga_get_powerplay_table_entry(struct pp_hwmgr
*hwmgr
,
1176 uint32_t entry_index
, struct pp_power_state
*power_state
,
1177 int (*call_back_func
)(struct pp_hwmgr
*, void *,
1178 struct pp_power_state
*, void *, uint32_t))
1181 const ATOM_Tonga_State_Array
* state_arrays
;
1182 const ATOM_Tonga_State
*state_entry
;
1183 const ATOM_Tonga_POWERPLAYTABLE
*pp_table
= get_powerplay_table(hwmgr
);
1185 PP_ASSERT_WITH_CODE((NULL
!= pp_table
), "Missing PowerPlay Table!", return -1;);
1186 power_state
->classification
.bios_index
= entry_index
;
1188 if (pp_table
->sHeader
.ucTableFormatRevision
>=
1189 ATOM_Tonga_TABLE_REVISION_TONGA
) {
1190 state_arrays
= (ATOM_Tonga_State_Array
*)(((unsigned long)pp_table
) +
1191 le16_to_cpu(pp_table
->usStateArrayOffset
));
1193 PP_ASSERT_WITH_CODE((0 < pp_table
->usStateArrayOffset
),
1194 "Invalid PowerPlay Table State Array Offset.", return -1);
1195 PP_ASSERT_WITH_CODE((0 < state_arrays
->ucNumEntries
),
1196 "Invalid PowerPlay Table State Array.", return -1);
1197 PP_ASSERT_WITH_CODE((entry_index
<= state_arrays
->ucNumEntries
),
1198 "Invalid PowerPlay Table State Array Entry.", return -1);
1200 state_entry
= &(state_arrays
->states
[entry_index
]);
1202 result
= call_back_func(hwmgr
, (void *)state_entry
, power_state
,
1204 make_classification_flags(hwmgr
,
1205 le16_to_cpu(state_entry
->usClassification
),
1206 le16_to_cpu(state_entry
->usClassification2
)));
1209 if (!result
&& (power_state
->classification
.flags
&
1210 PP_StateClassificationFlag_Boot
))
1211 result
= hwmgr
->hwmgr_func
->patch_boot_state(hwmgr
, &(power_state
->hardware
));