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>
26 #include "tonga_processpptables.h"
27 #include "ppatomctrl.h"
31 #include "cgs_common.h"
32 #include "tonga_pptable.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 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 cgs_atom_get_data_table(hwmgr
->device
,
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
;
163 PP_ASSERT_WITH_CODE((0 != vddc_lookup_pp_tables
->ucNumEntries
),
164 "Invalid CAC Leakage PowerPlay Table!", return 1);
166 table_size
= sizeof(uint32_t) +
167 sizeof(phm_ppt_v1_voltage_lookup_record
) * max_levels
;
169 table
= kzalloc(table_size
, GFP_KERNEL
);
174 memset(table
, 0x00, table_size
);
176 table
->count
= vddc_lookup_pp_tables
->ucNumEntries
;
178 for (i
= 0; i
< vddc_lookup_pp_tables
->ucNumEntries
; i
++) {
179 table
->entries
[i
].us_calculated
= 0;
180 table
->entries
[i
].us_vdd
=
181 vddc_lookup_pp_tables
->entries
[i
].usVdd
;
182 table
->entries
[i
].us_cac_low
=
183 vddc_lookup_pp_tables
->entries
[i
].usCACLow
;
184 table
->entries
[i
].us_cac_mid
=
185 vddc_lookup_pp_tables
->entries
[i
].usCACMid
;
186 table
->entries
[i
].us_cac_high
=
187 vddc_lookup_pp_tables
->entries
[i
].usCACHigh
;
190 *lookup_table
= table
;
196 * Private Function used during initialization.
197 * Initialize Platform Power Management Parameter table
198 * @param hwmgr Pointer to the hardware manager.
199 * @param atom_ppm_table Pointer to PPM table in VBIOS
201 static int get_platform_power_management_table(
202 struct pp_hwmgr
*hwmgr
,
203 ATOM_Tonga_PPM_Table
*atom_ppm_table
)
205 struct phm_ppm_table
*ptr
= kzalloc(sizeof(ATOM_Tonga_PPM_Table
), GFP_KERNEL
);
206 struct phm_ppt_v1_information
*pp_table_information
=
207 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
213 = atom_ppm_table
->ucPpmDesign
;
215 = atom_ppm_table
->usCpuCoreNumber
;
217 = atom_ppm_table
->ulPlatformTDP
;
218 ptr
->small_ac_platform_tdp
219 = atom_ppm_table
->ulSmallACPlatformTDP
;
221 = atom_ppm_table
->ulPlatformTDC
;
222 ptr
->small_ac_platform_tdc
223 = atom_ppm_table
->ulSmallACPlatformTDC
;
225 = atom_ppm_table
->ulApuTDP
;
227 = atom_ppm_table
->ulDGpuTDP
;
229 = atom_ppm_table
->ulDGpuUlvPower
;
231 = atom_ppm_table
->ulTjmax
;
233 pp_table_information
->ppm_parameter_table
= ptr
;
239 * Private Function used during initialization.
240 * Initialize TDP limits for DPM2
241 * @param hwmgr Pointer to the hardware manager.
242 * @param powerplay_table Pointer to the PowerPlay Table.
244 static int init_dpm_2_parameters(
245 struct pp_hwmgr
*hwmgr
,
246 const ATOM_Tonga_POWERPLAYTABLE
*powerplay_table
250 struct phm_ppt_v1_information
*pp_table_information
= (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
251 ATOM_Tonga_PPM_Table
*atom_ppm_table
;
252 uint32_t disable_ppm
= 0;
253 uint32_t disable_power_control
= 0;
255 pp_table_information
->us_ulv_voltage_offset
=
256 le16_to_cpu(powerplay_table
->usUlvVoltageOffset
);
258 pp_table_information
->ppm_parameter_table
= NULL
;
259 pp_table_information
->vddc_lookup_table
= NULL
;
260 pp_table_information
->vddgfx_lookup_table
= NULL
;
262 hwmgr
->platform_descriptor
.TDPODLimit
=
263 le16_to_cpu(powerplay_table
->usPowerControlLimit
);
264 hwmgr
->platform_descriptor
.TDPAdjustment
= 0;
265 hwmgr
->platform_descriptor
.VidAdjustment
= 0;
266 hwmgr
->platform_descriptor
.VidAdjustmentPolarity
= 0;
267 hwmgr
->platform_descriptor
.VidMinLimit
= 0;
268 hwmgr
->platform_descriptor
.VidMaxLimit
= 1500000;
269 hwmgr
->platform_descriptor
.VidStep
= 6250;
271 disable_power_control
= 0;
272 if (0 == disable_power_control
) {
273 /* enable TDP overdrive (PowerControl) feature as well if supported */
274 if (hwmgr
->platform_descriptor
.TDPODLimit
!= 0)
275 phm_cap_set(hwmgr
->platform_descriptor
.platformCaps
,
276 PHM_PlatformCaps_PowerControl
);
279 if (0 != powerplay_table
->usVddcLookupTableOffset
) {
280 const ATOM_Tonga_Voltage_Lookup_Table
*pVddcCACTable
=
281 (ATOM_Tonga_Voltage_Lookup_Table
*)(((unsigned long)powerplay_table
) +
282 le16_to_cpu(powerplay_table
->usVddcLookupTableOffset
));
284 result
= get_vddc_lookup_table(hwmgr
,
285 &pp_table_information
->vddc_lookup_table
, pVddcCACTable
, 16);
288 if (0 != powerplay_table
->usVddgfxLookupTableOffset
) {
289 const ATOM_Tonga_Voltage_Lookup_Table
*pVddgfxCACTable
=
290 (ATOM_Tonga_Voltage_Lookup_Table
*)(((unsigned long)powerplay_table
) +
291 le16_to_cpu(powerplay_table
->usVddgfxLookupTableOffset
));
293 result
= get_vddc_lookup_table(hwmgr
,
294 &pp_table_information
->vddgfx_lookup_table
, pVddgfxCACTable
, 16);
298 if (0 == disable_ppm
) {
299 atom_ppm_table
= (ATOM_Tonga_PPM_Table
*)
300 (((unsigned long)powerplay_table
) + le16_to_cpu(powerplay_table
->usPPMTableOffset
));
302 if (0 != powerplay_table
->usPPMTableOffset
) {
303 if (get_platform_power_management_table(hwmgr
, atom_ppm_table
) == 0) {
304 phm_cap_set(hwmgr
->platform_descriptor
.platformCaps
,
305 PHM_PlatformCaps_EnablePlatformPowerManagement
);
313 static int get_valid_clk(
314 struct pp_hwmgr
*hwmgr
,
315 struct phm_clock_array
**clk_table
,
316 const phm_ppt_v1_clock_voltage_dependency_table
* clk_volt_pp_table
319 uint32_t table_size
, i
;
320 struct phm_clock_array
*table
;
322 PP_ASSERT_WITH_CODE((0 != clk_volt_pp_table
->count
),
323 "Invalid PowerPlay Table!", return -1);
325 table_size
= sizeof(uint32_t) +
326 sizeof(uint32_t) * clk_volt_pp_table
->count
;
328 table
= kzalloc(table_size
, GFP_KERNEL
);
333 memset(table
, 0x00, table_size
);
335 table
->count
= (uint32_t)clk_volt_pp_table
->count
;
337 for (i
= 0; i
< table
->count
; i
++)
338 table
->values
[i
] = (uint32_t)clk_volt_pp_table
->entries
[i
].clk
;
345 static int get_hard_limits(
346 struct pp_hwmgr
*hwmgr
,
347 struct phm_clock_and_voltage_limits
*limits
,
348 const ATOM_Tonga_Hard_Limit_Table
* limitable
351 PP_ASSERT_WITH_CODE((0 != limitable
->ucNumEntries
), "Invalid PowerPlay Table!", return -1);
353 /* currently we always take entries[0] parameters */
354 limits
->sclk
= (uint32_t)limitable
->entries
[0].ulSCLKLimit
;
355 limits
->mclk
= (uint32_t)limitable
->entries
[0].ulMCLKLimit
;
356 limits
->vddc
= (uint16_t)limitable
->entries
[0].usVddcLimit
;
357 limits
->vddci
= (uint16_t)limitable
->entries
[0].usVddciLimit
;
358 limits
->vddgfx
= (uint16_t)limitable
->entries
[0].usVddgfxLimit
;
363 static int get_mclk_voltage_dependency_table(
364 struct pp_hwmgr
*hwmgr
,
365 phm_ppt_v1_clock_voltage_dependency_table
**pp_tonga_mclk_dep_table
,
366 const ATOM_Tonga_MCLK_Dependency_Table
* mclk_dep_table
369 uint32_t table_size
, i
;
370 phm_ppt_v1_clock_voltage_dependency_table
*mclk_table
;
372 PP_ASSERT_WITH_CODE((0 != mclk_dep_table
->ucNumEntries
),
373 "Invalid PowerPlay Table!", return -1);
375 table_size
= sizeof(uint32_t) + sizeof(phm_ppt_v1_clock_voltage_dependency_record
)
376 * mclk_dep_table
->ucNumEntries
;
378 mclk_table
= kzalloc(table_size
, GFP_KERNEL
);
380 if (NULL
== mclk_table
)
383 memset(mclk_table
, 0x00, table_size
);
385 mclk_table
->count
= (uint32_t)mclk_dep_table
->ucNumEntries
;
387 for (i
= 0; i
< mclk_dep_table
->ucNumEntries
; i
++) {
388 mclk_table
->entries
[i
].vddInd
=
389 mclk_dep_table
->entries
[i
].ucVddcInd
;
390 mclk_table
->entries
[i
].vdd_offset
=
391 mclk_dep_table
->entries
[i
].usVddgfxOffset
;
392 mclk_table
->entries
[i
].vddci
=
393 mclk_dep_table
->entries
[i
].usVddci
;
394 mclk_table
->entries
[i
].mvdd
=
395 mclk_dep_table
->entries
[i
].usMvdd
;
396 mclk_table
->entries
[i
].clk
=
397 mclk_dep_table
->entries
[i
].ulMclk
;
400 *pp_tonga_mclk_dep_table
= mclk_table
;
405 static int get_sclk_voltage_dependency_table(
406 struct pp_hwmgr
*hwmgr
,
407 phm_ppt_v1_clock_voltage_dependency_table
**pp_tonga_sclk_dep_table
,
408 const PPTable_Generic_SubTable_Header
*sclk_dep_table
411 uint32_t table_size
, i
;
412 phm_ppt_v1_clock_voltage_dependency_table
*sclk_table
;
414 if (sclk_dep_table
->ucRevId
< 1) {
415 const ATOM_Tonga_SCLK_Dependency_Table
*tonga_table
=
416 (ATOM_Tonga_SCLK_Dependency_Table
*)sclk_dep_table
;
418 PP_ASSERT_WITH_CODE((0 != tonga_table
->ucNumEntries
),
419 "Invalid PowerPlay Table!", return -1);
421 table_size
= sizeof(uint32_t) + sizeof(phm_ppt_v1_clock_voltage_dependency_record
)
422 * tonga_table
->ucNumEntries
;
424 sclk_table
= kzalloc(table_size
, GFP_KERNEL
);
426 if (NULL
== sclk_table
)
429 memset(sclk_table
, 0x00, table_size
);
431 sclk_table
->count
= (uint32_t)tonga_table
->ucNumEntries
;
433 for (i
= 0; i
< tonga_table
->ucNumEntries
; i
++) {
434 sclk_table
->entries
[i
].vddInd
=
435 tonga_table
->entries
[i
].ucVddInd
;
436 sclk_table
->entries
[i
].vdd_offset
=
437 tonga_table
->entries
[i
].usVddcOffset
;
438 sclk_table
->entries
[i
].clk
=
439 tonga_table
->entries
[i
].ulSclk
;
440 sclk_table
->entries
[i
].cks_enable
=
441 (((tonga_table
->entries
[i
].ucCKSVOffsetandDisable
& 0x80) >> 7) == 0) ? 1 : 0;
442 sclk_table
->entries
[i
].cks_voffset
=
443 (tonga_table
->entries
[i
].ucCKSVOffsetandDisable
& 0x7F);
446 const ATOM_Polaris_SCLK_Dependency_Table
*polaris_table
=
447 (ATOM_Polaris_SCLK_Dependency_Table
*)sclk_dep_table
;
449 PP_ASSERT_WITH_CODE((0 != polaris_table
->ucNumEntries
),
450 "Invalid PowerPlay Table!", return -1);
452 table_size
= sizeof(uint32_t) + sizeof(phm_ppt_v1_clock_voltage_dependency_record
)
453 * polaris_table
->ucNumEntries
;
455 sclk_table
= kzalloc(table_size
, GFP_KERNEL
);
457 if (NULL
== sclk_table
)
460 memset(sclk_table
, 0x00, table_size
);
462 sclk_table
->count
= (uint32_t)polaris_table
->ucNumEntries
;
464 for (i
= 0; i
< polaris_table
->ucNumEntries
; i
++) {
465 sclk_table
->entries
[i
].vddInd
=
466 polaris_table
->entries
[i
].ucVddInd
;
467 sclk_table
->entries
[i
].vdd_offset
=
468 polaris_table
->entries
[i
].usVddcOffset
;
469 sclk_table
->entries
[i
].clk
=
470 polaris_table
->entries
[i
].ulSclk
;
471 sclk_table
->entries
[i
].cks_enable
=
472 (((polaris_table
->entries
[i
].ucCKSVOffsetandDisable
& 0x80) >> 7) == 0) ? 1 : 0;
473 sclk_table
->entries
[i
].cks_voffset
=
474 (polaris_table
->entries
[i
].ucCKSVOffsetandDisable
& 0x7F);
475 sclk_table
->entries
[i
].sclk_offset
= polaris_table
->entries
[i
].ulSclkOffset
;
478 *pp_tonga_sclk_dep_table
= sclk_table
;
483 static int get_pcie_table(
484 struct pp_hwmgr
*hwmgr
,
485 phm_ppt_v1_pcie_table
**pp_tonga_pcie_table
,
486 const PPTable_Generic_SubTable_Header
* pTable
489 uint32_t table_size
, i
, pcie_count
;
490 phm_ppt_v1_pcie_table
*pcie_table
;
491 struct phm_ppt_v1_information
*pp_table_information
=
492 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
494 if (pTable
->ucRevId
< 1) {
495 const ATOM_Tonga_PCIE_Table
*atom_pcie_table
= (ATOM_Tonga_PCIE_Table
*)pTable
;
496 PP_ASSERT_WITH_CODE((atom_pcie_table
->ucNumEntries
!= 0),
497 "Invalid PowerPlay Table!", return -1);
499 table_size
= sizeof(uint32_t) +
500 sizeof(phm_ppt_v1_pcie_record
) * atom_pcie_table
->ucNumEntries
;
502 pcie_table
= kzalloc(table_size
, GFP_KERNEL
);
504 if (pcie_table
== NULL
)
507 memset(pcie_table
, 0x00, table_size
);
510 * Make sure the number of pcie entries are less than or equal to sclk dpm levels.
511 * Since first PCIE entry is for ULV, #pcie has to be <= SclkLevel + 1.
513 pcie_count
= (pp_table_information
->vdd_dep_on_sclk
->count
) + 1;
514 if ((uint32_t)atom_pcie_table
->ucNumEntries
<= pcie_count
)
515 pcie_count
= (uint32_t)atom_pcie_table
->ucNumEntries
;
517 printk(KERN_ERR
"[ powerplay ] Number of Pcie Entries exceed the number of SCLK Dpm Levels! \
518 Disregarding the excess entries... \n");
520 pcie_table
->count
= pcie_count
;
522 for (i
= 0; i
< pcie_count
; i
++) {
523 pcie_table
->entries
[i
].gen_speed
=
524 atom_pcie_table
->entries
[i
].ucPCIEGenSpeed
;
525 pcie_table
->entries
[i
].lane_width
=
526 atom_pcie_table
->entries
[i
].usPCIELaneWidth
;
529 *pp_tonga_pcie_table
= pcie_table
;
531 /* Polaris10/Polaris11 and newer. */
532 const ATOM_Polaris10_PCIE_Table
*atom_pcie_table
= (ATOM_Polaris10_PCIE_Table
*)pTable
;
533 PP_ASSERT_WITH_CODE((atom_pcie_table
->ucNumEntries
!= 0),
534 "Invalid PowerPlay Table!", return -1);
536 table_size
= sizeof(uint32_t) +
537 sizeof(phm_ppt_v1_pcie_record
) * atom_pcie_table
->ucNumEntries
;
539 pcie_table
= kzalloc(table_size
, GFP_KERNEL
);
541 if (pcie_table
== NULL
)
544 memset(pcie_table
, 0x00, table_size
);
547 * Make sure the number of pcie entries are less than or equal to sclk dpm levels.
548 * Since first PCIE entry is for ULV, #pcie has to be <= SclkLevel + 1.
550 pcie_count
= (pp_table_information
->vdd_dep_on_sclk
->count
) + 1;
551 if ((uint32_t)atom_pcie_table
->ucNumEntries
<= pcie_count
)
552 pcie_count
= (uint32_t)atom_pcie_table
->ucNumEntries
;
554 printk(KERN_ERR
"[ powerplay ] Number of Pcie Entries exceed the number of SCLK Dpm Levels! \
555 Disregarding the excess entries... \n");
557 pcie_table
->count
= pcie_count
;
559 for (i
= 0; i
< pcie_count
; i
++) {
560 pcie_table
->entries
[i
].gen_speed
=
561 atom_pcie_table
->entries
[i
].ucPCIEGenSpeed
;
562 pcie_table
->entries
[i
].lane_width
=
563 atom_pcie_table
->entries
[i
].usPCIELaneWidth
;
564 pcie_table
->entries
[i
].pcie_sclk
=
565 atom_pcie_table
->entries
[i
].ulPCIE_Sclk
;
568 *pp_tonga_pcie_table
= pcie_table
;
574 static int get_cac_tdp_table(
575 struct pp_hwmgr
*hwmgr
,
576 struct phm_cac_tdp_table
**cac_tdp_table
,
577 const PPTable_Generic_SubTable_Header
* table
581 struct phm_cac_tdp_table
*tdp_table
;
583 table_size
= sizeof(uint32_t) + sizeof(struct phm_cac_tdp_table
);
584 tdp_table
= kzalloc(table_size
, GFP_KERNEL
);
586 if (NULL
== tdp_table
)
589 memset(tdp_table
, 0x00, table_size
);
591 hwmgr
->dyn_state
.cac_dtp_table
= kzalloc(table_size
, GFP_KERNEL
);
593 if (NULL
== hwmgr
->dyn_state
.cac_dtp_table
) {
598 memset(hwmgr
->dyn_state
.cac_dtp_table
, 0x00, table_size
);
600 if (table
->ucRevId
< 3) {
601 const ATOM_Tonga_PowerTune_Table
*tonga_table
=
602 (ATOM_Tonga_PowerTune_Table
*)table
;
603 tdp_table
->usTDP
= tonga_table
->usTDP
;
604 tdp_table
->usConfigurableTDP
=
605 tonga_table
->usConfigurableTDP
;
606 tdp_table
->usTDC
= tonga_table
->usTDC
;
607 tdp_table
->usBatteryPowerLimit
=
608 tonga_table
->usBatteryPowerLimit
;
609 tdp_table
->usSmallPowerLimit
=
610 tonga_table
->usSmallPowerLimit
;
611 tdp_table
->usLowCACLeakage
=
612 tonga_table
->usLowCACLeakage
;
613 tdp_table
->usHighCACLeakage
=
614 tonga_table
->usHighCACLeakage
;
615 tdp_table
->usMaximumPowerDeliveryLimit
=
616 tonga_table
->usMaximumPowerDeliveryLimit
;
617 tdp_table
->usDefaultTargetOperatingTemp
=
618 tonga_table
->usTjMax
;
619 tdp_table
->usTargetOperatingTemp
=
620 tonga_table
->usTjMax
; /*Set the initial temp to the same as default */
621 tdp_table
->usPowerTuneDataSetID
=
622 tonga_table
->usPowerTuneDataSetID
;
623 tdp_table
->usSoftwareShutdownTemp
=
624 tonga_table
->usSoftwareShutdownTemp
;
625 tdp_table
->usClockStretchAmount
=
626 tonga_table
->usClockStretchAmount
;
627 } else { /* Fiji and newer */
628 const ATOM_Fiji_PowerTune_Table
*fijitable
=
629 (ATOM_Fiji_PowerTune_Table
*)table
;
630 tdp_table
->usTDP
= fijitable
->usTDP
;
631 tdp_table
->usConfigurableTDP
= fijitable
->usConfigurableTDP
;
632 tdp_table
->usTDC
= fijitable
->usTDC
;
633 tdp_table
->usBatteryPowerLimit
= fijitable
->usBatteryPowerLimit
;
634 tdp_table
->usSmallPowerLimit
= fijitable
->usSmallPowerLimit
;
635 tdp_table
->usLowCACLeakage
= fijitable
->usLowCACLeakage
;
636 tdp_table
->usHighCACLeakage
= fijitable
->usHighCACLeakage
;
637 tdp_table
->usMaximumPowerDeliveryLimit
=
638 fijitable
->usMaximumPowerDeliveryLimit
;
639 tdp_table
->usDefaultTargetOperatingTemp
=
641 tdp_table
->usTargetOperatingTemp
=
642 fijitable
->usTjMax
; /*Set the initial temp to the same as default */
643 tdp_table
->usPowerTuneDataSetID
=
644 fijitable
->usPowerTuneDataSetID
;
645 tdp_table
->usSoftwareShutdownTemp
=
646 fijitable
->usSoftwareShutdownTemp
;
647 tdp_table
->usClockStretchAmount
=
648 fijitable
->usClockStretchAmount
;
649 tdp_table
->usTemperatureLimitHotspot
=
650 fijitable
->usTemperatureLimitHotspot
;
651 tdp_table
->usTemperatureLimitLiquid1
=
652 fijitable
->usTemperatureLimitLiquid1
;
653 tdp_table
->usTemperatureLimitLiquid2
=
654 fijitable
->usTemperatureLimitLiquid2
;
655 tdp_table
->usTemperatureLimitVrVddc
=
656 fijitable
->usTemperatureLimitVrVddc
;
657 tdp_table
->usTemperatureLimitVrMvdd
=
658 fijitable
->usTemperatureLimitVrMvdd
;
659 tdp_table
->usTemperatureLimitPlx
=
660 fijitable
->usTemperatureLimitPlx
;
661 tdp_table
->ucLiquid1_I2C_address
=
662 fijitable
->ucLiquid1_I2C_address
;
663 tdp_table
->ucLiquid2_I2C_address
=
664 fijitable
->ucLiquid2_I2C_address
;
665 tdp_table
->ucLiquid_I2C_Line
=
666 fijitable
->ucLiquid_I2C_Line
;
667 tdp_table
->ucVr_I2C_address
= fijitable
->ucVr_I2C_address
;
668 tdp_table
->ucVr_I2C_Line
= fijitable
->ucVr_I2C_Line
;
669 tdp_table
->ucPlx_I2C_address
= fijitable
->ucPlx_I2C_address
;
670 tdp_table
->ucPlx_I2C_Line
= fijitable
->ucPlx_I2C_Line
;
673 *cac_tdp_table
= tdp_table
;
678 static int get_mm_clock_voltage_table(
679 struct pp_hwmgr
*hwmgr
,
680 phm_ppt_v1_mm_clock_voltage_dependency_table
**tonga_mm_table
,
681 const ATOM_Tonga_MM_Dependency_Table
* mm_dependency_table
684 uint32_t table_size
, i
;
685 const ATOM_Tonga_MM_Dependency_Record
*mm_dependency_record
;
686 phm_ppt_v1_mm_clock_voltage_dependency_table
*mm_table
;
688 PP_ASSERT_WITH_CODE((0 != mm_dependency_table
->ucNumEntries
),
689 "Invalid PowerPlay Table!", return -1);
690 table_size
= sizeof(uint32_t) +
691 sizeof(phm_ppt_v1_mm_clock_voltage_dependency_record
)
692 * mm_dependency_table
->ucNumEntries
;
693 mm_table
= kzalloc(table_size
, GFP_KERNEL
);
695 if (NULL
== mm_table
)
698 memset(mm_table
, 0x00, table_size
);
700 mm_table
->count
= mm_dependency_table
->ucNumEntries
;
702 for (i
= 0; i
< mm_dependency_table
->ucNumEntries
; i
++) {
703 mm_dependency_record
= &mm_dependency_table
->entries
[i
];
704 mm_table
->entries
[i
].vddcInd
= mm_dependency_record
->ucVddcInd
;
705 mm_table
->entries
[i
].vddgfx_offset
= mm_dependency_record
->usVddgfxOffset
;
706 mm_table
->entries
[i
].aclk
= mm_dependency_record
->ulAClk
;
707 mm_table
->entries
[i
].samclock
= mm_dependency_record
->ulSAMUClk
;
708 mm_table
->entries
[i
].eclk
= mm_dependency_record
->ulEClk
;
709 mm_table
->entries
[i
].vclk
= mm_dependency_record
->ulVClk
;
710 mm_table
->entries
[i
].dclk
= mm_dependency_record
->ulDClk
;
713 *tonga_mm_table
= mm_table
;
719 * Private Function used during initialization.
720 * Initialize clock voltage dependency
721 * @param hwmgr Pointer to the hardware manager.
722 * @param powerplay_table Pointer to the PowerPlay Table.
724 static int init_clock_voltage_dependency(
725 struct pp_hwmgr
*hwmgr
,
726 const ATOM_Tonga_POWERPLAYTABLE
*powerplay_table
730 struct phm_ppt_v1_information
*pp_table_information
=
731 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
733 const ATOM_Tonga_MM_Dependency_Table
*mm_dependency_table
=
734 (const ATOM_Tonga_MM_Dependency_Table
*)(((unsigned long) powerplay_table
) +
735 le16_to_cpu(powerplay_table
->usMMDependencyTableOffset
));
736 const PPTable_Generic_SubTable_Header
*pPowerTuneTable
=
737 (const PPTable_Generic_SubTable_Header
*)(((unsigned long) powerplay_table
) +
738 le16_to_cpu(powerplay_table
->usPowerTuneTableOffset
));
739 const ATOM_Tonga_MCLK_Dependency_Table
*mclk_dep_table
=
740 (const ATOM_Tonga_MCLK_Dependency_Table
*)(((unsigned long) powerplay_table
) +
741 le16_to_cpu(powerplay_table
->usMclkDependencyTableOffset
));
742 const PPTable_Generic_SubTable_Header
*sclk_dep_table
=
743 (const PPTable_Generic_SubTable_Header
*)(((unsigned long) powerplay_table
) +
744 le16_to_cpu(powerplay_table
->usSclkDependencyTableOffset
));
745 const ATOM_Tonga_Hard_Limit_Table
*pHardLimits
=
746 (const ATOM_Tonga_Hard_Limit_Table
*)(((unsigned long) powerplay_table
) +
747 le16_to_cpu(powerplay_table
->usHardLimitTableOffset
));
748 const PPTable_Generic_SubTable_Header
*pcie_table
=
749 (const PPTable_Generic_SubTable_Header
*)(((unsigned long) powerplay_table
) +
750 le16_to_cpu(powerplay_table
->usPCIETableOffset
));
752 pp_table_information
->vdd_dep_on_sclk
= NULL
;
753 pp_table_information
->vdd_dep_on_mclk
= NULL
;
754 pp_table_information
->mm_dep_table
= NULL
;
755 pp_table_information
->pcie_table
= NULL
;
757 if (powerplay_table
->usMMDependencyTableOffset
!= 0)
758 result
= get_mm_clock_voltage_table(hwmgr
,
759 &pp_table_information
->mm_dep_table
, mm_dependency_table
);
761 if (result
== 0 && powerplay_table
->usPowerTuneTableOffset
!= 0)
762 result
= get_cac_tdp_table(hwmgr
,
763 &pp_table_information
->cac_dtp_table
, pPowerTuneTable
);
765 if (result
== 0 && powerplay_table
->usSclkDependencyTableOffset
!= 0)
766 result
= get_sclk_voltage_dependency_table(hwmgr
,
767 &pp_table_information
->vdd_dep_on_sclk
, sclk_dep_table
);
769 if (result
== 0 && powerplay_table
->usMclkDependencyTableOffset
!= 0)
770 result
= get_mclk_voltage_dependency_table(hwmgr
,
771 &pp_table_information
->vdd_dep_on_mclk
, mclk_dep_table
);
773 if (result
== 0 && powerplay_table
->usPCIETableOffset
!= 0)
774 result
= get_pcie_table(hwmgr
,
775 &pp_table_information
->pcie_table
, pcie_table
);
777 if (result
== 0 && powerplay_table
->usHardLimitTableOffset
!= 0)
778 result
= get_hard_limits(hwmgr
,
779 &pp_table_information
->max_clock_voltage_on_dc
, pHardLimits
);
781 hwmgr
->dyn_state
.max_clock_voltage_on_dc
.sclk
=
782 pp_table_information
->max_clock_voltage_on_dc
.sclk
;
783 hwmgr
->dyn_state
.max_clock_voltage_on_dc
.mclk
=
784 pp_table_information
->max_clock_voltage_on_dc
.mclk
;
785 hwmgr
->dyn_state
.max_clock_voltage_on_dc
.vddc
=
786 pp_table_information
->max_clock_voltage_on_dc
.vddc
;
787 hwmgr
->dyn_state
.max_clock_voltage_on_dc
.vddci
=
788 pp_table_information
->max_clock_voltage_on_dc
.vddci
;
790 if (result
== 0 && (NULL
!= pp_table_information
->vdd_dep_on_mclk
)
791 && (0 != pp_table_information
->vdd_dep_on_mclk
->count
))
792 result
= get_valid_clk(hwmgr
, &pp_table_information
->valid_mclk_values
,
793 pp_table_information
->vdd_dep_on_mclk
);
795 if (result
== 0 && (NULL
!= pp_table_information
->vdd_dep_on_sclk
)
796 && (0 != pp_table_information
->vdd_dep_on_sclk
->count
))
797 result
= get_valid_clk(hwmgr
, &pp_table_information
->valid_sclk_values
,
798 pp_table_information
->vdd_dep_on_sclk
);
803 /** Retrieves the (signed) Overdrive limits from VBIOS.
804 * The max engine clock, memory clock and max temperature come from the firmware info table.
806 * The information is placed into the platform descriptor.
808 * @param hwmgr source of the VBIOS table and owner of the platform descriptor to be updated.
809 * @param powerplay_table the address of the PowerPlay table.
811 * @return 1 as long as the firmware info table was present and of a supported version.
813 static int init_over_drive_limits(
814 struct pp_hwmgr
*hwmgr
,
815 const ATOM_Tonga_POWERPLAYTABLE
*powerplay_table
)
817 hwmgr
->platform_descriptor
.overdriveLimit
.engineClock
=
818 le16_to_cpu(powerplay_table
->ulMaxODEngineClock
);
819 hwmgr
->platform_descriptor
.overdriveLimit
.memoryClock
=
820 le16_to_cpu(powerplay_table
->ulMaxODMemoryClock
);
822 hwmgr
->platform_descriptor
.minOverdriveVDDC
= 0;
823 hwmgr
->platform_descriptor
.maxOverdriveVDDC
= 0;
824 hwmgr
->platform_descriptor
.overdriveVDDCStep
= 0;
826 if (hwmgr
->platform_descriptor
.overdriveLimit
.engineClock
> 0 \
827 && hwmgr
->platform_descriptor
.overdriveLimit
.memoryClock
> 0) {
828 phm_cap_set(hwmgr
->platform_descriptor
.platformCaps
,
829 PHM_PlatformCaps_ACOverdriveSupport
);
836 * Private Function used during initialization.
837 * Inspect the PowerPlay table for obvious signs of corruption.
838 * @param hwmgr Pointer to the hardware manager.
839 * @param powerplay_table Pointer to the PowerPlay Table.
840 * @exception This implementation always returns 1.
842 static int init_thermal_controller(
843 struct pp_hwmgr
*hwmgr
,
844 const ATOM_Tonga_POWERPLAYTABLE
*powerplay_table
847 const PPTable_Generic_SubTable_Header
*fan_table
;
848 ATOM_Tonga_Thermal_Controller
*thermal_controller
;
850 thermal_controller
= (ATOM_Tonga_Thermal_Controller
*)
851 (((unsigned long)powerplay_table
) +
852 le16_to_cpu(powerplay_table
->usThermalControllerOffset
));
853 PP_ASSERT_WITH_CODE((0 != powerplay_table
->usThermalControllerOffset
),
854 "Thermal controller table not set!", return -1);
856 hwmgr
->thermal_controller
.ucType
= thermal_controller
->ucType
;
857 hwmgr
->thermal_controller
.ucI2cLine
= thermal_controller
->ucI2cLine
;
858 hwmgr
->thermal_controller
.ucI2cAddress
= thermal_controller
->ucI2cAddress
;
860 hwmgr
->thermal_controller
.fanInfo
.bNoFan
=
861 (0 != (thermal_controller
->ucFanParameters
& ATOM_TONGA_PP_FANPARAMETERS_NOFAN
));
863 hwmgr
->thermal_controller
.fanInfo
.ucTachometerPulsesPerRevolution
=
864 thermal_controller
->ucFanParameters
&
865 ATOM_TONGA_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK
;
867 hwmgr
->thermal_controller
.fanInfo
.ulMinRPM
868 = thermal_controller
->ucFanMinRPM
* 100UL;
869 hwmgr
->thermal_controller
.fanInfo
.ulMaxRPM
870 = thermal_controller
->ucFanMaxRPM
* 100UL;
874 ATOM_TONGA_PP_THERMALCONTROLLER_NONE
!= hwmgr
->thermal_controller
.ucType
,
875 PHM_PlatformCaps_ThermalController
878 if (0 == powerplay_table
->usFanTableOffset
)
881 fan_table
= (const PPTable_Generic_SubTable_Header
*)
882 (((unsigned long)powerplay_table
) +
883 le16_to_cpu(powerplay_table
->usFanTableOffset
));
885 PP_ASSERT_WITH_CODE((0 != powerplay_table
->usFanTableOffset
),
886 "Fan table not set!", return -1);
887 PP_ASSERT_WITH_CODE((0 < fan_table
->ucRevId
),
888 "Unsupported fan table format!", return -1);
890 hwmgr
->thermal_controller
.advanceFanControlParameters
.ulCycleDelay
892 phm_cap_set(hwmgr
->platform_descriptor
.platformCaps
,
893 PHM_PlatformCaps_MicrocodeFanControl
);
895 if (fan_table
->ucRevId
< 8) {
896 const ATOM_Tonga_Fan_Table
*tonga_fan_table
=
897 (ATOM_Tonga_Fan_Table
*)fan_table
;
898 hwmgr
->thermal_controller
.advanceFanControlParameters
.ucTHyst
899 = tonga_fan_table
->ucTHyst
;
900 hwmgr
->thermal_controller
.advanceFanControlParameters
.usTMin
901 = tonga_fan_table
->usTMin
;
902 hwmgr
->thermal_controller
.advanceFanControlParameters
.usTMed
903 = tonga_fan_table
->usTMed
;
904 hwmgr
->thermal_controller
.advanceFanControlParameters
.usTHigh
905 = tonga_fan_table
->usTHigh
;
906 hwmgr
->thermal_controller
.advanceFanControlParameters
.usPWMMin
907 = tonga_fan_table
->usPWMMin
;
908 hwmgr
->thermal_controller
.advanceFanControlParameters
.usPWMMed
909 = tonga_fan_table
->usPWMMed
;
910 hwmgr
->thermal_controller
.advanceFanControlParameters
.usPWMHigh
911 = tonga_fan_table
->usPWMHigh
;
912 hwmgr
->thermal_controller
.advanceFanControlParameters
.usTMax
913 = 10900; /* hard coded */
914 hwmgr
->thermal_controller
.advanceFanControlParameters
.usTMax
915 = tonga_fan_table
->usTMax
;
916 hwmgr
->thermal_controller
.advanceFanControlParameters
.ucFanControlMode
917 = tonga_fan_table
->ucFanControlMode
;
918 hwmgr
->thermal_controller
.advanceFanControlParameters
.usDefaultMaxFanPWM
919 = tonga_fan_table
->usFanPWMMax
;
920 hwmgr
->thermal_controller
.advanceFanControlParameters
.usDefaultFanOutputSensitivity
922 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanOutputSensitivity
923 = tonga_fan_table
->usFanOutputSensitivity
;
924 hwmgr
->thermal_controller
.advanceFanControlParameters
.usDefaultMaxFanRPM
925 = tonga_fan_table
->usFanRPMMax
;
926 hwmgr
->thermal_controller
.advanceFanControlParameters
.ulMinFanSCLKAcousticLimit
927 = (tonga_fan_table
->ulMinFanSCLKAcousticLimit
/ 100); /* PPTable stores it in 10Khz unit for 2 decimal places. SMC wants MHz. */
928 hwmgr
->thermal_controller
.advanceFanControlParameters
.ucTargetTemperature
929 = tonga_fan_table
->ucTargetTemperature
;
930 hwmgr
->thermal_controller
.advanceFanControlParameters
.ucMinimumPWMLimit
931 = tonga_fan_table
->ucMinimumPWMLimit
;
933 const ATOM_Fiji_Fan_Table
*fiji_fan_table
=
934 (ATOM_Fiji_Fan_Table
*)fan_table
;
935 hwmgr
->thermal_controller
.advanceFanControlParameters
.ucTHyst
936 = fiji_fan_table
->ucTHyst
;
937 hwmgr
->thermal_controller
.advanceFanControlParameters
.usTMin
938 = fiji_fan_table
->usTMin
;
939 hwmgr
->thermal_controller
.advanceFanControlParameters
.usTMed
940 = fiji_fan_table
->usTMed
;
941 hwmgr
->thermal_controller
.advanceFanControlParameters
.usTHigh
942 = fiji_fan_table
->usTHigh
;
943 hwmgr
->thermal_controller
.advanceFanControlParameters
.usPWMMin
944 = fiji_fan_table
->usPWMMin
;
945 hwmgr
->thermal_controller
.advanceFanControlParameters
.usPWMMed
946 = fiji_fan_table
->usPWMMed
;
947 hwmgr
->thermal_controller
.advanceFanControlParameters
.usPWMHigh
948 = fiji_fan_table
->usPWMHigh
;
949 hwmgr
->thermal_controller
.advanceFanControlParameters
.usTMax
950 = fiji_fan_table
->usTMax
;
951 hwmgr
->thermal_controller
.advanceFanControlParameters
.ucFanControlMode
952 = fiji_fan_table
->ucFanControlMode
;
953 hwmgr
->thermal_controller
.advanceFanControlParameters
.usDefaultMaxFanPWM
954 = fiji_fan_table
->usFanPWMMax
;
955 hwmgr
->thermal_controller
.advanceFanControlParameters
.usDefaultFanOutputSensitivity
957 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanOutputSensitivity
958 = fiji_fan_table
->usFanOutputSensitivity
;
959 hwmgr
->thermal_controller
.advanceFanControlParameters
.usDefaultMaxFanRPM
960 = fiji_fan_table
->usFanRPMMax
;
961 hwmgr
->thermal_controller
.advanceFanControlParameters
.ulMinFanSCLKAcousticLimit
962 = (fiji_fan_table
->ulMinFanSCLKAcousticLimit
/ 100); /* PPTable stores it in 10Khz unit for 2 decimal places. SMC wants MHz. */
963 hwmgr
->thermal_controller
.advanceFanControlParameters
.ucTargetTemperature
964 = fiji_fan_table
->ucTargetTemperature
;
965 hwmgr
->thermal_controller
.advanceFanControlParameters
.ucMinimumPWMLimit
966 = fiji_fan_table
->ucMinimumPWMLimit
;
968 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanGainEdge
969 = fiji_fan_table
->usFanGainEdge
;
970 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanGainHotspot
971 = fiji_fan_table
->usFanGainHotspot
;
972 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanGainLiquid
973 = fiji_fan_table
->usFanGainLiquid
;
974 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanGainVrVddc
975 = fiji_fan_table
->usFanGainVrVddc
;
976 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanGainVrMvdd
977 = fiji_fan_table
->usFanGainVrMvdd
;
978 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanGainPlx
979 = fiji_fan_table
->usFanGainPlx
;
980 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanGainHbm
981 = fiji_fan_table
->usFanGainHbm
;
988 * Private Function used during initialization.
989 * Inspect the PowerPlay table for obvious signs of corruption.
990 * @param hwmgr Pointer to the hardware manager.
991 * @param powerplay_table Pointer to the PowerPlay Table.
992 * @exception 2 if the powerplay table is incorrect.
994 static int check_powerplay_tables(
995 struct pp_hwmgr
*hwmgr
,
996 const ATOM_Tonga_POWERPLAYTABLE
*powerplay_table
999 const ATOM_Tonga_State_Array
*state_arrays
;
1001 state_arrays
= (ATOM_Tonga_State_Array
*)(((unsigned long)powerplay_table
) +
1002 le16_to_cpu(powerplay_table
->usStateArrayOffset
));
1004 PP_ASSERT_WITH_CODE((ATOM_Tonga_TABLE_REVISION_TONGA
<=
1005 powerplay_table
->sHeader
.ucTableFormatRevision
),
1006 "Unsupported PPTable format!", return -1);
1007 PP_ASSERT_WITH_CODE((0 != powerplay_table
->usStateArrayOffset
),
1008 "State table is not set!", return -1);
1009 PP_ASSERT_WITH_CODE((0 < powerplay_table
->sHeader
.usStructureSize
),
1010 "Invalid PowerPlay Table!", return -1);
1011 PP_ASSERT_WITH_CODE((0 < state_arrays
->ucNumEntries
),
1012 "Invalid PowerPlay Table!", return -1);
1017 int tonga_pp_tables_initialize(struct pp_hwmgr
*hwmgr
)
1020 const ATOM_Tonga_POWERPLAYTABLE
*powerplay_table
;
1022 hwmgr
->pptable
= kzalloc(sizeof(struct phm_ppt_v1_information
), GFP_KERNEL
);
1024 PP_ASSERT_WITH_CODE((NULL
!= hwmgr
->pptable
),
1025 "Failed to allocate hwmgr->pptable!", return -ENOMEM
);
1027 memset(hwmgr
->pptable
, 0x00, sizeof(struct phm_ppt_v1_information
));
1029 powerplay_table
= get_powerplay_table(hwmgr
);
1031 PP_ASSERT_WITH_CODE((NULL
!= powerplay_table
),
1032 "Missing PowerPlay Table!", return -1);
1034 result
= check_powerplay_tables(hwmgr
, powerplay_table
);
1036 PP_ASSERT_WITH_CODE((result
== 0),
1037 "check_powerplay_tables failed", return result
);
1039 result
= set_platform_caps(hwmgr
,
1040 le32_to_cpu(powerplay_table
->ulPlatformCaps
));
1042 PP_ASSERT_WITH_CODE((result
== 0),
1043 "set_platform_caps failed", return result
);
1045 result
= init_thermal_controller(hwmgr
, powerplay_table
);
1047 PP_ASSERT_WITH_CODE((result
== 0),
1048 "init_thermal_controller failed", return result
);
1050 result
= init_over_drive_limits(hwmgr
, powerplay_table
);
1052 PP_ASSERT_WITH_CODE((result
== 0),
1053 "init_over_drive_limits failed", return result
);
1055 result
= init_clock_voltage_dependency(hwmgr
, powerplay_table
);
1057 PP_ASSERT_WITH_CODE((result
== 0),
1058 "init_clock_voltage_dependency failed", return result
);
1060 result
= init_dpm_2_parameters(hwmgr
, powerplay_table
);
1062 PP_ASSERT_WITH_CODE((result
== 0),
1063 "init_dpm_2_parameters failed", return result
);
1068 int tonga_pp_tables_uninitialize(struct pp_hwmgr
*hwmgr
)
1070 struct phm_ppt_v1_information
*pp_table_information
=
1071 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
1073 kfree(pp_table_information
->vdd_dep_on_sclk
);
1074 pp_table_information
->vdd_dep_on_sclk
= NULL
;
1076 kfree(pp_table_information
->vdd_dep_on_mclk
);
1077 pp_table_information
->vdd_dep_on_mclk
= NULL
;
1079 kfree(pp_table_information
->valid_mclk_values
);
1080 pp_table_information
->valid_mclk_values
= NULL
;
1082 kfree(pp_table_information
->valid_sclk_values
);
1083 pp_table_information
->valid_sclk_values
= NULL
;
1085 kfree(pp_table_information
->vddc_lookup_table
);
1086 pp_table_information
->vddc_lookup_table
= NULL
;
1088 kfree(pp_table_information
->vddgfx_lookup_table
);
1089 pp_table_information
->vddgfx_lookup_table
= NULL
;
1091 kfree(pp_table_information
->mm_dep_table
);
1092 pp_table_information
->mm_dep_table
= NULL
;
1094 kfree(pp_table_information
->cac_dtp_table
);
1095 pp_table_information
->cac_dtp_table
= NULL
;
1097 kfree(hwmgr
->dyn_state
.cac_dtp_table
);
1098 hwmgr
->dyn_state
.cac_dtp_table
= NULL
;
1100 kfree(pp_table_information
->ppm_parameter_table
);
1101 pp_table_information
->ppm_parameter_table
= NULL
;
1103 kfree(pp_table_information
->pcie_table
);
1104 pp_table_information
->pcie_table
= NULL
;
1106 kfree(hwmgr
->pptable
);
1107 hwmgr
->pptable
= NULL
;
1112 const struct pp_table_func tonga_pptable_funcs
= {
1113 .pptable_init
= tonga_pp_tables_initialize
,
1114 .pptable_fini
= tonga_pp_tables_uninitialize
,
1117 int tonga_get_number_of_powerplay_table_entries(struct pp_hwmgr
*hwmgr
)
1119 const ATOM_Tonga_State_Array
* state_arrays
;
1120 const ATOM_Tonga_POWERPLAYTABLE
*pp_table
= get_powerplay_table(hwmgr
);
1122 PP_ASSERT_WITH_CODE((NULL
!= pp_table
),
1123 "Missing PowerPlay Table!", return -1);
1124 PP_ASSERT_WITH_CODE((pp_table
->sHeader
.ucTableFormatRevision
>=
1125 ATOM_Tonga_TABLE_REVISION_TONGA
),
1126 "Incorrect PowerPlay table revision!", return -1);
1128 state_arrays
= (ATOM_Tonga_State_Array
*)(((unsigned long)pp_table
) +
1129 le16_to_cpu(pp_table
->usStateArrayOffset
));
1131 return (uint32_t)(state_arrays
->ucNumEntries
);
1135 * Private function to convert flags stored in the BIOS to software flags in PowerPlay.
1137 static uint32_t make_classification_flags(struct pp_hwmgr
*hwmgr
,
1138 uint16_t classification
, uint16_t classification2
)
1140 uint32_t result
= 0;
1142 if (classification
& ATOM_PPLIB_CLASSIFICATION_BOOT
)
1143 result
|= PP_StateClassificationFlag_Boot
;
1145 if (classification
& ATOM_PPLIB_CLASSIFICATION_THERMAL
)
1146 result
|= PP_StateClassificationFlag_Thermal
;
1148 if (classification
& ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE
)
1149 result
|= PP_StateClassificationFlag_LimitedPowerSource
;
1151 if (classification
& ATOM_PPLIB_CLASSIFICATION_REST
)
1152 result
|= PP_StateClassificationFlag_Rest
;
1154 if (classification
& ATOM_PPLIB_CLASSIFICATION_FORCED
)
1155 result
|= PP_StateClassificationFlag_Forced
;
1157 if (classification
& ATOM_PPLIB_CLASSIFICATION_ACPI
)
1158 result
|= PP_StateClassificationFlag_ACPI
;
1160 if (classification2
& ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2
)
1161 result
|= PP_StateClassificationFlag_LimitedPowerSource_2
;
1167 * Create a Power State out of an entry in the PowerPlay table.
1168 * This function is called by the hardware back-end.
1169 * @param hwmgr Pointer to the hardware manager.
1170 * @param entry_index The index of the entry to be extracted from the table.
1171 * @param power_state The address of the PowerState instance being created.
1172 * @return -1 if the entry cannot be retrieved.
1174 int tonga_get_powerplay_table_entry(struct pp_hwmgr
*hwmgr
,
1175 uint32_t entry_index
, struct pp_power_state
*power_state
,
1176 int (*call_back_func
)(struct pp_hwmgr
*, void *,
1177 struct pp_power_state
*, void *, uint32_t))
1180 const ATOM_Tonga_State_Array
* state_arrays
;
1181 const ATOM_Tonga_State
*state_entry
;
1182 const ATOM_Tonga_POWERPLAYTABLE
*pp_table
= get_powerplay_table(hwmgr
);
1184 PP_ASSERT_WITH_CODE((NULL
!= pp_table
), "Missing PowerPlay Table!", return -1;);
1185 power_state
->classification
.bios_index
= entry_index
;
1187 if (pp_table
->sHeader
.ucTableFormatRevision
>=
1188 ATOM_Tonga_TABLE_REVISION_TONGA
) {
1189 state_arrays
= (ATOM_Tonga_State_Array
*)(((unsigned long)pp_table
) +
1190 le16_to_cpu(pp_table
->usStateArrayOffset
));
1192 PP_ASSERT_WITH_CODE((0 < pp_table
->usStateArrayOffset
),
1193 "Invalid PowerPlay Table State Array Offset.", return -1);
1194 PP_ASSERT_WITH_CODE((0 < state_arrays
->ucNumEntries
),
1195 "Invalid PowerPlay Table State Array.", return -1);
1196 PP_ASSERT_WITH_CODE((entry_index
<= state_arrays
->ucNumEntries
),
1197 "Invalid PowerPlay Table State Array Entry.", return -1);
1199 state_entry
= &(state_arrays
->states
[entry_index
]);
1201 result
= call_back_func(hwmgr
, (void *)state_entry
, power_state
,
1203 make_classification_flags(hwmgr
,
1204 le16_to_cpu(state_entry
->usClassification
),
1205 le16_to_cpu(state_entry
->usClassification2
)));
1208 if (!result
&& (power_state
->classification
.flags
&
1209 PP_StateClassificationFlag_Boot
))
1210 result
= hwmgr
->hwmgr_func
->patch_boot_state(hwmgr
, &(power_state
->hardware
));