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
);
143 table_address
= (ATOM_Tonga_POWERPLAYTABLE
*)
144 cgs_atom_get_data_table(hwmgr
->device
, index
, &size
, &frev
, &crev
);
146 hwmgr
->soft_pp_table
= table_address
; /*Cache the result in RAM.*/
148 return table_address
;
151 static int get_vddc_lookup_table(
152 struct pp_hwmgr
*hwmgr
,
153 phm_ppt_v1_voltage_lookup_table
**lookup_table
,
154 const ATOM_Tonga_Voltage_Lookup_Table
*vddc_lookup_pp_tables
,
158 uint32_t table_size
, i
;
159 phm_ppt_v1_voltage_lookup_table
*table
;
161 PP_ASSERT_WITH_CODE((0 != vddc_lookup_pp_tables
->ucNumEntries
),
162 "Invalid CAC Leakage PowerPlay Table!", return 1);
164 table_size
= sizeof(uint32_t) +
165 sizeof(phm_ppt_v1_voltage_lookup_record
) * max_levels
;
167 table
= (phm_ppt_v1_voltage_lookup_table
*)
168 kzalloc(table_size
, GFP_KERNEL
);
173 memset(table
, 0x00, table_size
);
175 table
->count
= vddc_lookup_pp_tables
->ucNumEntries
;
177 for (i
= 0; i
< vddc_lookup_pp_tables
->ucNumEntries
; i
++) {
178 table
->entries
[i
].us_calculated
= 0;
179 table
->entries
[i
].us_vdd
=
180 vddc_lookup_pp_tables
->entries
[i
].usVdd
;
181 table
->entries
[i
].us_cac_low
=
182 vddc_lookup_pp_tables
->entries
[i
].usCACLow
;
183 table
->entries
[i
].us_cac_mid
=
184 vddc_lookup_pp_tables
->entries
[i
].usCACMid
;
185 table
->entries
[i
].us_cac_high
=
186 vddc_lookup_pp_tables
->entries
[i
].usCACHigh
;
189 *lookup_table
= table
;
195 * Private Function used during initialization.
196 * Initialize Platform Power Management Parameter table
197 * @param hwmgr Pointer to the hardware manager.
198 * @param atom_ppm_table Pointer to PPM table in VBIOS
200 static int get_platform_power_management_table(
201 struct pp_hwmgr
*hwmgr
,
202 ATOM_Tonga_PPM_Table
*atom_ppm_table
)
204 struct phm_ppm_table
*ptr
= kzalloc(sizeof(ATOM_Tonga_PPM_Table
), GFP_KERNEL
);
205 struct phm_ppt_v1_information
*pp_table_information
=
206 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
212 = atom_ppm_table
->ucPpmDesign
;
214 = atom_ppm_table
->usCpuCoreNumber
;
216 = atom_ppm_table
->ulPlatformTDP
;
217 ptr
->small_ac_platform_tdp
218 = atom_ppm_table
->ulSmallACPlatformTDP
;
220 = atom_ppm_table
->ulPlatformTDC
;
221 ptr
->small_ac_platform_tdc
222 = atom_ppm_table
->ulSmallACPlatformTDC
;
224 = atom_ppm_table
->ulApuTDP
;
226 = atom_ppm_table
->ulDGpuTDP
;
228 = atom_ppm_table
->ulDGpuUlvPower
;
230 = atom_ppm_table
->ulTjmax
;
232 pp_table_information
->ppm_parameter_table
= ptr
;
238 * Private Function used during initialization.
239 * Initialize TDP limits for DPM2
240 * @param hwmgr Pointer to the hardware manager.
241 * @param powerplay_table Pointer to the PowerPlay Table.
243 static int init_dpm_2_parameters(
244 struct pp_hwmgr
*hwmgr
,
245 const ATOM_Tonga_POWERPLAYTABLE
*powerplay_table
249 struct phm_ppt_v1_information
*pp_table_information
= (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
250 ATOM_Tonga_PPM_Table
*atom_ppm_table
;
251 uint32_t disable_ppm
= 0;
252 uint32_t disable_power_control
= 0;
254 pp_table_information
->us_ulv_voltage_offset
=
255 le16_to_cpu(powerplay_table
->usUlvVoltageOffset
);
257 pp_table_information
->ppm_parameter_table
= NULL
;
258 pp_table_information
->vddc_lookup_table
= NULL
;
259 pp_table_information
->vddgfx_lookup_table
= NULL
;
261 hwmgr
->platform_descriptor
.TDPODLimit
=
262 le16_to_cpu(powerplay_table
->usPowerControlLimit
);
263 hwmgr
->platform_descriptor
.TDPAdjustment
= 0;
264 hwmgr
->platform_descriptor
.VidAdjustment
= 0;
265 hwmgr
->platform_descriptor
.VidAdjustmentPolarity
= 0;
266 hwmgr
->platform_descriptor
.VidMinLimit
= 0;
267 hwmgr
->platform_descriptor
.VidMaxLimit
= 1500000;
268 hwmgr
->platform_descriptor
.VidStep
= 6250;
270 disable_power_control
= 0;
271 if (0 == disable_power_control
) {
272 /* enable TDP overdrive (PowerControl) feature as well if supported */
273 if (hwmgr
->platform_descriptor
.TDPODLimit
!= 0)
274 phm_cap_set(hwmgr
->platform_descriptor
.platformCaps
,
275 PHM_PlatformCaps_PowerControl
);
278 if (0 != powerplay_table
->usVddcLookupTableOffset
) {
279 const ATOM_Tonga_Voltage_Lookup_Table
*pVddcCACTable
=
280 (ATOM_Tonga_Voltage_Lookup_Table
*)(((unsigned long)powerplay_table
) +
281 le16_to_cpu(powerplay_table
->usVddcLookupTableOffset
));
283 result
= get_vddc_lookup_table(hwmgr
,
284 &pp_table_information
->vddc_lookup_table
, pVddcCACTable
, 16);
287 if (0 != powerplay_table
->usVddgfxLookupTableOffset
) {
288 const ATOM_Tonga_Voltage_Lookup_Table
*pVddgfxCACTable
=
289 (ATOM_Tonga_Voltage_Lookup_Table
*)(((unsigned long)powerplay_table
) +
290 le16_to_cpu(powerplay_table
->usVddgfxLookupTableOffset
));
292 result
= get_vddc_lookup_table(hwmgr
,
293 &pp_table_information
->vddgfx_lookup_table
, pVddgfxCACTable
, 16);
297 if (0 == disable_ppm
) {
298 atom_ppm_table
= (ATOM_Tonga_PPM_Table
*)
299 (((unsigned long)powerplay_table
) + le16_to_cpu(powerplay_table
->usPPMTableOffset
));
301 if (0 != powerplay_table
->usPPMTableOffset
) {
302 if (1 == get_platform_power_management_table(hwmgr
, atom_ppm_table
)) {
303 phm_cap_set(hwmgr
->platform_descriptor
.platformCaps
,
304 PHM_PlatformCaps_EnablePlatformPowerManagement
);
312 static int get_valid_clk(
313 struct pp_hwmgr
*hwmgr
,
314 struct phm_clock_array
**clk_table
,
315 const phm_ppt_v1_clock_voltage_dependency_table
* clk_volt_pp_table
318 uint32_t table_size
, i
;
319 struct phm_clock_array
*table
;
321 PP_ASSERT_WITH_CODE((0 != clk_volt_pp_table
->count
),
322 "Invalid PowerPlay Table!", return -1);
324 table_size
= sizeof(uint32_t) +
325 sizeof(uint32_t) * clk_volt_pp_table
->count
;
327 table
= (struct phm_clock_array
*)kzalloc(table_size
, GFP_KERNEL
);
332 memset(table
, 0x00, table_size
);
334 table
->count
= (uint32_t)clk_volt_pp_table
->count
;
336 for (i
= 0; i
< table
->count
; i
++)
337 table
->values
[i
] = (uint32_t)clk_volt_pp_table
->entries
[i
].clk
;
344 static int get_hard_limits(
345 struct pp_hwmgr
*hwmgr
,
346 struct phm_clock_and_voltage_limits
*limits
,
347 const ATOM_Tonga_Hard_Limit_Table
* limitable
350 PP_ASSERT_WITH_CODE((0 != limitable
->ucNumEntries
), "Invalid PowerPlay Table!", return -1);
352 /* currently we always take entries[0] parameters */
353 limits
->sclk
= (uint32_t)limitable
->entries
[0].ulSCLKLimit
;
354 limits
->mclk
= (uint32_t)limitable
->entries
[0].ulMCLKLimit
;
355 limits
->vddc
= (uint16_t)limitable
->entries
[0].usVddcLimit
;
356 limits
->vddci
= (uint16_t)limitable
->entries
[0].usVddciLimit
;
357 limits
->vddgfx
= (uint16_t)limitable
->entries
[0].usVddgfxLimit
;
362 static int get_mclk_voltage_dependency_table(
363 struct pp_hwmgr
*hwmgr
,
364 phm_ppt_v1_clock_voltage_dependency_table
**pp_tonga_mclk_dep_table
,
365 const ATOM_Tonga_MCLK_Dependency_Table
* mclk_dep_table
368 uint32_t table_size
, i
;
369 phm_ppt_v1_clock_voltage_dependency_table
*mclk_table
;
371 PP_ASSERT_WITH_CODE((0 != mclk_dep_table
->ucNumEntries
),
372 "Invalid PowerPlay Table!", return -1);
374 table_size
= sizeof(uint32_t) + sizeof(phm_ppt_v1_clock_voltage_dependency_record
)
375 * mclk_dep_table
->ucNumEntries
;
377 mclk_table
= (phm_ppt_v1_clock_voltage_dependency_table
*)
378 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 ATOM_Tonga_SCLK_Dependency_Table
* sclk_dep_table
411 uint32_t table_size
, i
;
412 phm_ppt_v1_clock_voltage_dependency_table
*sclk_table
;
414 PP_ASSERT_WITH_CODE((0 != sclk_dep_table
->ucNumEntries
),
415 "Invalid PowerPlay Table!", return -1);
417 table_size
= sizeof(uint32_t) + sizeof(phm_ppt_v1_clock_voltage_dependency_record
)
418 * sclk_dep_table
->ucNumEntries
;
420 sclk_table
= (phm_ppt_v1_clock_voltage_dependency_table
*)
421 kzalloc(table_size
, GFP_KERNEL
);
423 if (NULL
== sclk_table
)
426 memset(sclk_table
, 0x00, table_size
);
428 sclk_table
->count
= (uint32_t)sclk_dep_table
->ucNumEntries
;
430 for (i
= 0; i
< sclk_dep_table
->ucNumEntries
; i
++) {
431 sclk_table
->entries
[i
].vddInd
=
432 sclk_dep_table
->entries
[i
].ucVddInd
;
433 sclk_table
->entries
[i
].vdd_offset
=
434 sclk_dep_table
->entries
[i
].usVddcOffset
;
435 sclk_table
->entries
[i
].clk
=
436 sclk_dep_table
->entries
[i
].ulSclk
;
437 sclk_table
->entries
[i
].cks_enable
=
438 (((sclk_dep_table
->entries
[i
].ucCKSVOffsetandDisable
& 0x80) >> 7) == 0) ? 1 : 0;
439 sclk_table
->entries
[i
].cks_voffset
=
440 (sclk_dep_table
->entries
[i
].ucCKSVOffsetandDisable
& 0x7F);
443 *pp_tonga_sclk_dep_table
= sclk_table
;
448 static int get_pcie_table(
449 struct pp_hwmgr
*hwmgr
,
450 phm_ppt_v1_pcie_table
**pp_tonga_pcie_table
,
451 const ATOM_Tonga_PCIE_Table
* atom_pcie_table
454 uint32_t table_size
, i
, pcie_count
;
455 phm_ppt_v1_pcie_table
*pcie_table
;
456 struct phm_ppt_v1_information
*pp_table_information
=
457 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
458 PP_ASSERT_WITH_CODE((0 != atom_pcie_table
->ucNumEntries
),
459 "Invalid PowerPlay Table!", return -1);
461 table_size
= sizeof(uint32_t) +
462 sizeof(phm_ppt_v1_pcie_record
) * atom_pcie_table
->ucNumEntries
;
464 pcie_table
= (phm_ppt_v1_pcie_table
*)kzalloc(table_size
, GFP_KERNEL
);
466 if (NULL
== pcie_table
)
469 memset(pcie_table
, 0x00, table_size
);
472 * Make sure the number of pcie entries are less than or equal to sclk dpm levels.
473 * Since first PCIE entry is for ULV, #pcie has to be <= SclkLevel + 1.
475 pcie_count
= (pp_table_information
->vdd_dep_on_sclk
->count
) + 1;
476 if ((uint32_t)atom_pcie_table
->ucNumEntries
<= pcie_count
)
477 pcie_count
= (uint32_t)atom_pcie_table
->ucNumEntries
;
479 printk(KERN_ERR
"[ powerplay ] Number of Pcie Entries exceed the number of SCLK Dpm Levels! \
480 Disregarding the excess entries... \n");
482 pcie_table
->count
= pcie_count
;
484 for (i
= 0; i
< pcie_count
; i
++) {
485 pcie_table
->entries
[i
].gen_speed
=
486 atom_pcie_table
->entries
[i
].ucPCIEGenSpeed
;
487 pcie_table
->entries
[i
].lane_width
=
488 atom_pcie_table
->entries
[i
].usPCIELaneWidth
;
491 *pp_tonga_pcie_table
= pcie_table
;
496 static int get_cac_tdp_table(
497 struct pp_hwmgr
*hwmgr
,
498 struct phm_cac_tdp_table
**cac_tdp_table
,
499 const PPTable_Generic_SubTable_Header
* table
503 struct phm_cac_tdp_table
*tdp_table
;
505 table_size
= sizeof(uint32_t) + sizeof(struct phm_cac_tdp_table
);
506 tdp_table
= kzalloc(table_size
, GFP_KERNEL
);
508 if (NULL
== tdp_table
)
511 memset(tdp_table
, 0x00, table_size
);
513 hwmgr
->dyn_state
.cac_dtp_table
= kzalloc(table_size
, GFP_KERNEL
);
515 if (NULL
== hwmgr
->dyn_state
.cac_dtp_table
)
518 memset(hwmgr
->dyn_state
.cac_dtp_table
, 0x00, table_size
);
520 if (table
->ucRevId
< 3) {
521 const ATOM_Tonga_PowerTune_Table
*tonga_table
=
522 (ATOM_Tonga_PowerTune_Table
*)table
;
523 tdp_table
->usTDP
= tonga_table
->usTDP
;
524 tdp_table
->usConfigurableTDP
=
525 tonga_table
->usConfigurableTDP
;
526 tdp_table
->usTDC
= tonga_table
->usTDC
;
527 tdp_table
->usBatteryPowerLimit
=
528 tonga_table
->usBatteryPowerLimit
;
529 tdp_table
->usSmallPowerLimit
=
530 tonga_table
->usSmallPowerLimit
;
531 tdp_table
->usLowCACLeakage
=
532 tonga_table
->usLowCACLeakage
;
533 tdp_table
->usHighCACLeakage
=
534 tonga_table
->usHighCACLeakage
;
535 tdp_table
->usMaximumPowerDeliveryLimit
=
536 tonga_table
->usMaximumPowerDeliveryLimit
;
537 tdp_table
->usDefaultTargetOperatingTemp
=
538 tonga_table
->usTjMax
;
539 tdp_table
->usTargetOperatingTemp
=
540 tonga_table
->usTjMax
; /*Set the initial temp to the same as default */
541 tdp_table
->usPowerTuneDataSetID
=
542 tonga_table
->usPowerTuneDataSetID
;
543 tdp_table
->usSoftwareShutdownTemp
=
544 tonga_table
->usSoftwareShutdownTemp
;
545 tdp_table
->usClockStretchAmount
=
546 tonga_table
->usClockStretchAmount
;
547 } else { /* Fiji and newer */
548 const ATOM_Fiji_PowerTune_Table
*fijitable
=
549 (ATOM_Fiji_PowerTune_Table
*)table
;
550 tdp_table
->usTDP
= fijitable
->usTDP
;
551 tdp_table
->usConfigurableTDP
= fijitable
->usConfigurableTDP
;
552 tdp_table
->usTDC
= fijitable
->usTDC
;
553 tdp_table
->usBatteryPowerLimit
= fijitable
->usBatteryPowerLimit
;
554 tdp_table
->usSmallPowerLimit
= fijitable
->usSmallPowerLimit
;
555 tdp_table
->usLowCACLeakage
= fijitable
->usLowCACLeakage
;
556 tdp_table
->usHighCACLeakage
= fijitable
->usHighCACLeakage
;
557 tdp_table
->usMaximumPowerDeliveryLimit
=
558 fijitable
->usMaximumPowerDeliveryLimit
;
559 tdp_table
->usDefaultTargetOperatingTemp
=
561 tdp_table
->usTargetOperatingTemp
=
562 fijitable
->usTjMax
; /*Set the initial temp to the same as default */
563 tdp_table
->usPowerTuneDataSetID
=
564 fijitable
->usPowerTuneDataSetID
;
565 tdp_table
->usSoftwareShutdownTemp
=
566 fijitable
->usSoftwareShutdownTemp
;
567 tdp_table
->usClockStretchAmount
=
568 fijitable
->usClockStretchAmount
;
569 tdp_table
->usTemperatureLimitHotspot
=
570 fijitable
->usTemperatureLimitHotspot
;
571 tdp_table
->usTemperatureLimitLiquid1
=
572 fijitable
->usTemperatureLimitLiquid1
;
573 tdp_table
->usTemperatureLimitLiquid2
=
574 fijitable
->usTemperatureLimitLiquid2
;
575 tdp_table
->usTemperatureLimitVrVddc
=
576 fijitable
->usTemperatureLimitVrVddc
;
577 tdp_table
->usTemperatureLimitVrMvdd
=
578 fijitable
->usTemperatureLimitVrMvdd
;
579 tdp_table
->usTemperatureLimitPlx
=
580 fijitable
->usTemperatureLimitPlx
;
581 tdp_table
->ucLiquid1_I2C_address
=
582 fijitable
->ucLiquid1_I2C_address
;
583 tdp_table
->ucLiquid2_I2C_address
=
584 fijitable
->ucLiquid2_I2C_address
;
585 tdp_table
->ucLiquid_I2C_Line
=
586 fijitable
->ucLiquid_I2C_Line
;
587 tdp_table
->ucVr_I2C_address
= fijitable
->ucVr_I2C_address
;
588 tdp_table
->ucVr_I2C_Line
= fijitable
->ucVr_I2C_Line
;
589 tdp_table
->ucPlx_I2C_address
= fijitable
->ucPlx_I2C_address
;
590 tdp_table
->ucPlx_I2C_Line
= fijitable
->ucPlx_I2C_Line
;
593 *cac_tdp_table
= tdp_table
;
598 static int get_mm_clock_voltage_table(
599 struct pp_hwmgr
*hwmgr
,
600 phm_ppt_v1_mm_clock_voltage_dependency_table
**tonga_mm_table
,
601 const ATOM_Tonga_MM_Dependency_Table
* mm_dependency_table
604 uint32_t table_size
, i
;
605 const ATOM_Tonga_MM_Dependency_Record
*mm_dependency_record
;
606 phm_ppt_v1_mm_clock_voltage_dependency_table
*mm_table
;
608 PP_ASSERT_WITH_CODE((0 != mm_dependency_table
->ucNumEntries
),
609 "Invalid PowerPlay Table!", return -1);
610 table_size
= sizeof(uint32_t) +
611 sizeof(phm_ppt_v1_mm_clock_voltage_dependency_record
)
612 * mm_dependency_table
->ucNumEntries
;
613 mm_table
= (phm_ppt_v1_mm_clock_voltage_dependency_table
*)
614 kzalloc(table_size
, GFP_KERNEL
);
616 if (NULL
== mm_table
)
619 memset(mm_table
, 0x00, table_size
);
621 mm_table
->count
= mm_dependency_table
->ucNumEntries
;
623 for (i
= 0; i
< mm_dependency_table
->ucNumEntries
; i
++) {
624 mm_dependency_record
= &mm_dependency_table
->entries
[i
];
625 mm_table
->entries
[i
].vddcInd
= mm_dependency_record
->ucVddcInd
;
626 mm_table
->entries
[i
].vddgfx_offset
= mm_dependency_record
->usVddgfxOffset
;
627 mm_table
->entries
[i
].aclk
= mm_dependency_record
->ulAClk
;
628 mm_table
->entries
[i
].samclock
= mm_dependency_record
->ulSAMUClk
;
629 mm_table
->entries
[i
].eclk
= mm_dependency_record
->ulEClk
;
630 mm_table
->entries
[i
].vclk
= mm_dependency_record
->ulVClk
;
631 mm_table
->entries
[i
].dclk
= mm_dependency_record
->ulDClk
;
634 *tonga_mm_table
= mm_table
;
640 * Private Function used during initialization.
641 * Initialize clock voltage dependency
642 * @param hwmgr Pointer to the hardware manager.
643 * @param powerplay_table Pointer to the PowerPlay Table.
645 static int init_clock_voltage_dependency(
646 struct pp_hwmgr
*hwmgr
,
647 const ATOM_Tonga_POWERPLAYTABLE
*powerplay_table
651 struct phm_ppt_v1_information
*pp_table_information
=
652 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
654 const ATOM_Tonga_MM_Dependency_Table
*mm_dependency_table
=
655 (const ATOM_Tonga_MM_Dependency_Table
*)(((unsigned long) powerplay_table
) +
656 le16_to_cpu(powerplay_table
->usMMDependencyTableOffset
));
657 const PPTable_Generic_SubTable_Header
*pPowerTuneTable
=
658 (const PPTable_Generic_SubTable_Header
*)(((unsigned long) powerplay_table
) +
659 le16_to_cpu(powerplay_table
->usPowerTuneTableOffset
));
660 const ATOM_Tonga_MCLK_Dependency_Table
*mclk_dep_table
=
661 (const ATOM_Tonga_MCLK_Dependency_Table
*)(((unsigned long) powerplay_table
) +
662 le16_to_cpu(powerplay_table
->usMclkDependencyTableOffset
));
663 const ATOM_Tonga_SCLK_Dependency_Table
*sclk_dep_table
=
664 (const ATOM_Tonga_SCLK_Dependency_Table
*)(((unsigned long) powerplay_table
) +
665 le16_to_cpu(powerplay_table
->usSclkDependencyTableOffset
));
666 const ATOM_Tonga_Hard_Limit_Table
*pHardLimits
=
667 (const ATOM_Tonga_Hard_Limit_Table
*)(((unsigned long) powerplay_table
) +
668 le16_to_cpu(powerplay_table
->usHardLimitTableOffset
));
669 const ATOM_Tonga_PCIE_Table
*pcie_table
=
670 (const ATOM_Tonga_PCIE_Table
*)(((unsigned long) powerplay_table
) +
671 le16_to_cpu(powerplay_table
->usPCIETableOffset
));
673 pp_table_information
->vdd_dep_on_sclk
= NULL
;
674 pp_table_information
->vdd_dep_on_mclk
= NULL
;
675 pp_table_information
->mm_dep_table
= NULL
;
676 pp_table_information
->pcie_table
= NULL
;
678 if (powerplay_table
->usMMDependencyTableOffset
!= 0)
679 result
= get_mm_clock_voltage_table(hwmgr
,
680 &pp_table_information
->mm_dep_table
, mm_dependency_table
);
682 if (result
== 0 && powerplay_table
->usPowerTuneTableOffset
!= 0)
683 result
= get_cac_tdp_table(hwmgr
,
684 &pp_table_information
->cac_dtp_table
, pPowerTuneTable
);
686 if (result
== 0 && powerplay_table
->usSclkDependencyTableOffset
!= 0)
687 result
= get_sclk_voltage_dependency_table(hwmgr
,
688 &pp_table_information
->vdd_dep_on_sclk
, sclk_dep_table
);
690 if (result
== 0 && powerplay_table
->usMclkDependencyTableOffset
!= 0)
691 result
= get_mclk_voltage_dependency_table(hwmgr
,
692 &pp_table_information
->vdd_dep_on_mclk
, mclk_dep_table
);
694 if (result
== 0 && powerplay_table
->usPCIETableOffset
!= 0)
695 result
= get_pcie_table(hwmgr
,
696 &pp_table_information
->pcie_table
, pcie_table
);
698 if (result
== 0 && powerplay_table
->usHardLimitTableOffset
!= 0)
699 result
= get_hard_limits(hwmgr
,
700 &pp_table_information
->max_clock_voltage_on_dc
, pHardLimits
);
702 hwmgr
->dyn_state
.max_clock_voltage_on_dc
.sclk
=
703 pp_table_information
->max_clock_voltage_on_dc
.sclk
;
704 hwmgr
->dyn_state
.max_clock_voltage_on_dc
.mclk
=
705 pp_table_information
->max_clock_voltage_on_dc
.mclk
;
706 hwmgr
->dyn_state
.max_clock_voltage_on_dc
.vddc
=
707 pp_table_information
->max_clock_voltage_on_dc
.vddc
;
708 hwmgr
->dyn_state
.max_clock_voltage_on_dc
.vddci
=
709 pp_table_information
->max_clock_voltage_on_dc
.vddci
;
711 if (result
== 0 && (NULL
!= pp_table_information
->vdd_dep_on_mclk
)
712 && (0 != pp_table_information
->vdd_dep_on_mclk
->count
))
713 result
= get_valid_clk(hwmgr
, &pp_table_information
->valid_mclk_values
,
714 pp_table_information
->vdd_dep_on_mclk
);
716 if (result
== 0 && (NULL
!= pp_table_information
->vdd_dep_on_sclk
)
717 && (0 != pp_table_information
->vdd_dep_on_sclk
->count
))
718 result
= get_valid_clk(hwmgr
, &pp_table_information
->valid_sclk_values
,
719 pp_table_information
->vdd_dep_on_sclk
);
724 /** Retrieves the (signed) Overdrive limits from VBIOS.
725 * The max engine clock, memory clock and max temperature come from the firmware info table.
727 * The information is placed into the platform descriptor.
729 * @param hwmgr source of the VBIOS table and owner of the platform descriptor to be updated.
730 * @param powerplay_table the address of the PowerPlay table.
732 * @return 1 as long as the firmware info table was present and of a supported version.
734 static int init_over_drive_limits(
735 struct pp_hwmgr
*hwmgr
,
736 const ATOM_Tonga_POWERPLAYTABLE
*powerplay_table
)
738 hwmgr
->platform_descriptor
.overdriveLimit
.engineClock
=
739 le16_to_cpu(powerplay_table
->ulMaxODEngineClock
);
740 hwmgr
->platform_descriptor
.overdriveLimit
.memoryClock
=
741 le16_to_cpu(powerplay_table
->ulMaxODMemoryClock
);
743 hwmgr
->platform_descriptor
.minOverdriveVDDC
= 0;
744 hwmgr
->platform_descriptor
.maxOverdriveVDDC
= 0;
745 hwmgr
->platform_descriptor
.overdriveVDDCStep
= 0;
747 if (hwmgr
->platform_descriptor
.overdriveLimit
.engineClock
> 0 \
748 && hwmgr
->platform_descriptor
.overdriveLimit
.memoryClock
> 0) {
749 phm_cap_set(hwmgr
->platform_descriptor
.platformCaps
,
750 PHM_PlatformCaps_ACOverdriveSupport
);
757 * Private Function used during initialization.
758 * Inspect the PowerPlay table for obvious signs of corruption.
759 * @param hwmgr Pointer to the hardware manager.
760 * @param powerplay_table Pointer to the PowerPlay Table.
761 * @exception This implementation always returns 1.
763 static int init_thermal_controller(
764 struct pp_hwmgr
*hwmgr
,
765 const ATOM_Tonga_POWERPLAYTABLE
*powerplay_table
768 const PPTable_Generic_SubTable_Header
*fan_table
;
769 ATOM_Tonga_Thermal_Controller
*thermal_controller
;
771 thermal_controller
= (ATOM_Tonga_Thermal_Controller
*)
772 (((unsigned long)powerplay_table
) +
773 le16_to_cpu(powerplay_table
->usThermalControllerOffset
));
774 PP_ASSERT_WITH_CODE((0 != powerplay_table
->usThermalControllerOffset
),
775 "Thermal controller table not set!", return -1);
777 hwmgr
->thermal_controller
.ucType
= thermal_controller
->ucType
;
778 hwmgr
->thermal_controller
.ucI2cLine
= thermal_controller
->ucI2cLine
;
779 hwmgr
->thermal_controller
.ucI2cAddress
= thermal_controller
->ucI2cAddress
;
781 hwmgr
->thermal_controller
.fanInfo
.bNoFan
=
782 (0 != (thermal_controller
->ucFanParameters
& ATOM_TONGA_PP_FANPARAMETERS_NOFAN
));
784 hwmgr
->thermal_controller
.fanInfo
.ucTachometerPulsesPerRevolution
=
785 thermal_controller
->ucFanParameters
&
786 ATOM_TONGA_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK
;
788 hwmgr
->thermal_controller
.fanInfo
.ulMinRPM
789 = thermal_controller
->ucFanMinRPM
* 100UL;
790 hwmgr
->thermal_controller
.fanInfo
.ulMaxRPM
791 = thermal_controller
->ucFanMaxRPM
* 100UL;
795 ATOM_TONGA_PP_THERMALCONTROLLER_NONE
!= hwmgr
->thermal_controller
.ucType
,
796 PHM_PlatformCaps_ThermalController
799 if (0 == powerplay_table
->usFanTableOffset
)
802 fan_table
= (const PPTable_Generic_SubTable_Header
*)
803 (((unsigned long)powerplay_table
) +
804 le16_to_cpu(powerplay_table
->usFanTableOffset
));
806 PP_ASSERT_WITH_CODE((0 != powerplay_table
->usFanTableOffset
),
807 "Fan table not set!", return -1);
808 PP_ASSERT_WITH_CODE((0 < fan_table
->ucRevId
),
809 "Unsupported fan table format!", return -1);
811 hwmgr
->thermal_controller
.advanceFanControlParameters
.ulCycleDelay
813 phm_cap_set(hwmgr
->platform_descriptor
.platformCaps
,
814 PHM_PlatformCaps_MicrocodeFanControl
);
816 if (fan_table
->ucRevId
< 8) {
817 const ATOM_Tonga_Fan_Table
*tonga_fan_table
=
818 (ATOM_Tonga_Fan_Table
*)fan_table
;
819 hwmgr
->thermal_controller
.advanceFanControlParameters
.ucTHyst
820 = tonga_fan_table
->ucTHyst
;
821 hwmgr
->thermal_controller
.advanceFanControlParameters
.usTMin
822 = tonga_fan_table
->usTMin
;
823 hwmgr
->thermal_controller
.advanceFanControlParameters
.usTMed
824 = tonga_fan_table
->usTMed
;
825 hwmgr
->thermal_controller
.advanceFanControlParameters
.usTHigh
826 = tonga_fan_table
->usTHigh
;
827 hwmgr
->thermal_controller
.advanceFanControlParameters
.usPWMMin
828 = tonga_fan_table
->usPWMMin
;
829 hwmgr
->thermal_controller
.advanceFanControlParameters
.usPWMMed
830 = tonga_fan_table
->usPWMMed
;
831 hwmgr
->thermal_controller
.advanceFanControlParameters
.usPWMHigh
832 = tonga_fan_table
->usPWMHigh
;
833 hwmgr
->thermal_controller
.advanceFanControlParameters
.usTMax
834 = 10900; /* hard coded */
835 hwmgr
->thermal_controller
.advanceFanControlParameters
.usTMax
836 = tonga_fan_table
->usTMax
;
837 hwmgr
->thermal_controller
.advanceFanControlParameters
.ucFanControlMode
838 = tonga_fan_table
->ucFanControlMode
;
839 hwmgr
->thermal_controller
.advanceFanControlParameters
.usDefaultMaxFanPWM
840 = tonga_fan_table
->usFanPWMMax
;
841 hwmgr
->thermal_controller
.advanceFanControlParameters
.usDefaultFanOutputSensitivity
843 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanOutputSensitivity
844 = tonga_fan_table
->usFanOutputSensitivity
;
845 hwmgr
->thermal_controller
.advanceFanControlParameters
.usDefaultMaxFanRPM
846 = tonga_fan_table
->usFanRPMMax
;
847 hwmgr
->thermal_controller
.advanceFanControlParameters
.ulMinFanSCLKAcousticLimit
848 = (tonga_fan_table
->ulMinFanSCLKAcousticLimit
/ 100); /* PPTable stores it in 10Khz unit for 2 decimal places. SMC wants MHz. */
849 hwmgr
->thermal_controller
.advanceFanControlParameters
.ucTargetTemperature
850 = tonga_fan_table
->ucTargetTemperature
;
851 hwmgr
->thermal_controller
.advanceFanControlParameters
.ucMinimumPWMLimit
852 = tonga_fan_table
->ucMinimumPWMLimit
;
854 const ATOM_Fiji_Fan_Table
*fiji_fan_table
=
855 (ATOM_Fiji_Fan_Table
*)fan_table
;
856 hwmgr
->thermal_controller
.advanceFanControlParameters
.ucTHyst
857 = fiji_fan_table
->ucTHyst
;
858 hwmgr
->thermal_controller
.advanceFanControlParameters
.usTMin
859 = fiji_fan_table
->usTMin
;
860 hwmgr
->thermal_controller
.advanceFanControlParameters
.usTMed
861 = fiji_fan_table
->usTMed
;
862 hwmgr
->thermal_controller
.advanceFanControlParameters
.usTHigh
863 = fiji_fan_table
->usTHigh
;
864 hwmgr
->thermal_controller
.advanceFanControlParameters
.usPWMMin
865 = fiji_fan_table
->usPWMMin
;
866 hwmgr
->thermal_controller
.advanceFanControlParameters
.usPWMMed
867 = fiji_fan_table
->usPWMMed
;
868 hwmgr
->thermal_controller
.advanceFanControlParameters
.usPWMHigh
869 = fiji_fan_table
->usPWMHigh
;
870 hwmgr
->thermal_controller
.advanceFanControlParameters
.usTMax
871 = fiji_fan_table
->usTMax
;
872 hwmgr
->thermal_controller
.advanceFanControlParameters
.ucFanControlMode
873 = fiji_fan_table
->ucFanControlMode
;
874 hwmgr
->thermal_controller
.advanceFanControlParameters
.usDefaultMaxFanPWM
875 = fiji_fan_table
->usFanPWMMax
;
876 hwmgr
->thermal_controller
.advanceFanControlParameters
.usDefaultFanOutputSensitivity
878 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanOutputSensitivity
879 = fiji_fan_table
->usFanOutputSensitivity
;
880 hwmgr
->thermal_controller
.advanceFanControlParameters
.usDefaultMaxFanRPM
881 = fiji_fan_table
->usFanRPMMax
;
882 hwmgr
->thermal_controller
.advanceFanControlParameters
.ulMinFanSCLKAcousticLimit
883 = (fiji_fan_table
->ulMinFanSCLKAcousticLimit
/ 100); /* PPTable stores it in 10Khz unit for 2 decimal places. SMC wants MHz. */
884 hwmgr
->thermal_controller
.advanceFanControlParameters
.ucTargetTemperature
885 = fiji_fan_table
->ucTargetTemperature
;
886 hwmgr
->thermal_controller
.advanceFanControlParameters
.ucMinimumPWMLimit
887 = fiji_fan_table
->ucMinimumPWMLimit
;
889 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanGainEdge
890 = fiji_fan_table
->usFanGainEdge
;
891 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanGainHotspot
892 = fiji_fan_table
->usFanGainHotspot
;
893 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanGainLiquid
894 = fiji_fan_table
->usFanGainLiquid
;
895 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanGainVrVddc
896 = fiji_fan_table
->usFanGainVrVddc
;
897 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanGainVrMvdd
898 = fiji_fan_table
->usFanGainVrMvdd
;
899 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanGainPlx
900 = fiji_fan_table
->usFanGainPlx
;
901 hwmgr
->thermal_controller
.advanceFanControlParameters
.usFanGainHbm
902 = fiji_fan_table
->usFanGainHbm
;
909 * Private Function used during initialization.
910 * Inspect the PowerPlay table for obvious signs of corruption.
911 * @param hwmgr Pointer to the hardware manager.
912 * @param powerplay_table Pointer to the PowerPlay Table.
913 * @exception 2 if the powerplay table is incorrect.
915 static int check_powerplay_tables(
916 struct pp_hwmgr
*hwmgr
,
917 const ATOM_Tonga_POWERPLAYTABLE
*powerplay_table
920 const ATOM_Tonga_State_Array
*state_arrays
;
922 state_arrays
= (ATOM_Tonga_State_Array
*)(((unsigned long)powerplay_table
) +
923 le16_to_cpu(powerplay_table
->usStateArrayOffset
));
925 PP_ASSERT_WITH_CODE((ATOM_Tonga_TABLE_REVISION_TONGA
<=
926 powerplay_table
->sHeader
.ucTableFormatRevision
),
927 "Unsupported PPTable format!", return -1);
928 PP_ASSERT_WITH_CODE((0 != powerplay_table
->usStateArrayOffset
),
929 "State table is not set!", return -1);
930 PP_ASSERT_WITH_CODE((0 < powerplay_table
->sHeader
.usStructureSize
),
931 "Invalid PowerPlay Table!", return -1);
932 PP_ASSERT_WITH_CODE((0 < state_arrays
->ucNumEntries
),
933 "Invalid PowerPlay Table!", return -1);
938 int tonga_pp_tables_initialize(struct pp_hwmgr
*hwmgr
)
941 const ATOM_Tonga_POWERPLAYTABLE
*powerplay_table
;
943 hwmgr
->pptable
= kzalloc(sizeof(struct phm_ppt_v1_information
), GFP_KERNEL
);
945 PP_ASSERT_WITH_CODE((NULL
!= hwmgr
->pptable
),
946 "Failed to allocate hwmgr->pptable!", return -ENOMEM
);
948 memset(hwmgr
->pptable
, 0x00, sizeof(struct phm_ppt_v1_information
));
950 powerplay_table
= get_powerplay_table(hwmgr
);
952 PP_ASSERT_WITH_CODE((NULL
!= powerplay_table
),
953 "Missing PowerPlay Table!", return -1);
955 result
= check_powerplay_tables(hwmgr
, powerplay_table
);
957 PP_ASSERT_WITH_CODE((result
== 0),
958 "check_powerplay_tables failed", return result
);
960 result
= set_platform_caps(hwmgr
,
961 le32_to_cpu(powerplay_table
->ulPlatformCaps
));
963 PP_ASSERT_WITH_CODE((result
== 0),
964 "set_platform_caps failed", return result
);
966 result
= init_thermal_controller(hwmgr
, powerplay_table
);
968 PP_ASSERT_WITH_CODE((result
== 0),
969 "init_thermal_controller failed", return result
);
971 result
= init_over_drive_limits(hwmgr
, powerplay_table
);
973 PP_ASSERT_WITH_CODE((result
== 0),
974 "init_over_drive_limits failed", return result
);
976 result
= init_clock_voltage_dependency(hwmgr
, powerplay_table
);
978 PP_ASSERT_WITH_CODE((result
== 0),
979 "init_clock_voltage_dependency failed", return result
);
981 result
= init_dpm_2_parameters(hwmgr
, powerplay_table
);
983 PP_ASSERT_WITH_CODE((result
== 0),
984 "init_dpm_2_parameters failed", return result
);
989 int tonga_pp_tables_uninitialize(struct pp_hwmgr
*hwmgr
)
992 struct phm_ppt_v1_information
*pp_table_information
=
993 (struct phm_ppt_v1_information
*)(hwmgr
->pptable
);
995 if (NULL
!= hwmgr
->soft_pp_table
) {
996 kfree(hwmgr
->soft_pp_table
);
997 hwmgr
->soft_pp_table
= NULL
;
1000 if (NULL
!= pp_table_information
->vdd_dep_on_sclk
)
1001 pp_table_information
->vdd_dep_on_sclk
= NULL
;
1003 if (NULL
!= pp_table_information
->vdd_dep_on_mclk
)
1004 pp_table_information
->vdd_dep_on_mclk
= NULL
;
1006 if (NULL
!= pp_table_information
->valid_mclk_values
)
1007 pp_table_information
->valid_mclk_values
= NULL
;
1009 if (NULL
!= pp_table_information
->valid_sclk_values
)
1010 pp_table_information
->valid_sclk_values
= NULL
;
1012 if (NULL
!= pp_table_information
->vddc_lookup_table
)
1013 pp_table_information
->vddc_lookup_table
= NULL
;
1015 if (NULL
!= pp_table_information
->vddgfx_lookup_table
)
1016 pp_table_information
->vddgfx_lookup_table
= NULL
;
1018 if (NULL
!= pp_table_information
->mm_dep_table
)
1019 pp_table_information
->mm_dep_table
= NULL
;
1021 if (NULL
!= pp_table_information
->cac_dtp_table
)
1022 pp_table_information
->cac_dtp_table
= NULL
;
1024 if (NULL
!= hwmgr
->dyn_state
.cac_dtp_table
)
1025 hwmgr
->dyn_state
.cac_dtp_table
= NULL
;
1027 if (NULL
!= pp_table_information
->ppm_parameter_table
)
1028 pp_table_information
->ppm_parameter_table
= NULL
;
1030 if (NULL
!= pp_table_information
->pcie_table
)
1031 pp_table_information
->pcie_table
= NULL
;
1033 if (NULL
!= hwmgr
->pptable
) {
1034 kfree(hwmgr
->pptable
);
1035 hwmgr
->pptable
= NULL
;
1041 const struct pp_table_func tonga_pptable_funcs
= {
1042 .pptable_init
= tonga_pp_tables_initialize
,
1043 .pptable_fini
= tonga_pp_tables_uninitialize
,
1046 int tonga_get_number_of_powerplay_table_entries(struct pp_hwmgr
*hwmgr
)
1048 const ATOM_Tonga_State_Array
* state_arrays
;
1049 const ATOM_Tonga_POWERPLAYTABLE
*pp_table
= get_powerplay_table(hwmgr
);
1051 PP_ASSERT_WITH_CODE((NULL
!= pp_table
),
1052 "Missing PowerPlay Table!", return -1);
1053 PP_ASSERT_WITH_CODE((pp_table
->sHeader
.ucTableFormatRevision
>=
1054 ATOM_Tonga_TABLE_REVISION_TONGA
),
1055 "Incorrect PowerPlay table revision!", return -1);
1057 state_arrays
= (ATOM_Tonga_State_Array
*)(((unsigned long)pp_table
) +
1058 le16_to_cpu(pp_table
->usStateArrayOffset
));
1060 return (uint32_t)(state_arrays
->ucNumEntries
);
1064 * Private function to convert flags stored in the BIOS to software flags in PowerPlay.
1066 static uint32_t make_classification_flags(struct pp_hwmgr
*hwmgr
,
1067 uint16_t classification
, uint16_t classification2
)
1069 uint32_t result
= 0;
1071 if (classification
& ATOM_PPLIB_CLASSIFICATION_BOOT
)
1072 result
|= PP_StateClassificationFlag_Boot
;
1074 if (classification
& ATOM_PPLIB_CLASSIFICATION_THERMAL
)
1075 result
|= PP_StateClassificationFlag_Thermal
;
1077 if (classification
& ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE
)
1078 result
|= PP_StateClassificationFlag_LimitedPowerSource
;
1080 if (classification
& ATOM_PPLIB_CLASSIFICATION_REST
)
1081 result
|= PP_StateClassificationFlag_Rest
;
1083 if (classification
& ATOM_PPLIB_CLASSIFICATION_FORCED
)
1084 result
|= PP_StateClassificationFlag_Forced
;
1086 if (classification
& ATOM_PPLIB_CLASSIFICATION_ACPI
)
1087 result
|= PP_StateClassificationFlag_ACPI
;
1089 if (classification2
& ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2
)
1090 result
|= PP_StateClassificationFlag_LimitedPowerSource_2
;
1096 * Create a Power State out of an entry in the PowerPlay table.
1097 * This function is called by the hardware back-end.
1098 * @param hwmgr Pointer to the hardware manager.
1099 * @param entry_index The index of the entry to be extracted from the table.
1100 * @param power_state The address of the PowerState instance being created.
1101 * @return -1 if the entry cannot be retrieved.
1103 int tonga_get_powerplay_table_entry(struct pp_hwmgr
*hwmgr
,
1104 uint32_t entry_index
, struct pp_power_state
*power_state
,
1105 int (*call_back_func
)(struct pp_hwmgr
*, void *,
1106 struct pp_power_state
*, void *, uint32_t))
1109 const ATOM_Tonga_State_Array
* state_arrays
;
1110 const ATOM_Tonga_State
*state_entry
;
1111 const ATOM_Tonga_POWERPLAYTABLE
*pp_table
= get_powerplay_table(hwmgr
);
1113 PP_ASSERT_WITH_CODE((NULL
!= pp_table
), "Missing PowerPlay Table!", return -1;);
1114 power_state
->classification
.bios_index
= entry_index
;
1116 if (pp_table
->sHeader
.ucTableFormatRevision
>=
1117 ATOM_Tonga_TABLE_REVISION_TONGA
) {
1118 state_arrays
= (ATOM_Tonga_State_Array
*)(((unsigned long)pp_table
) +
1119 le16_to_cpu(pp_table
->usStateArrayOffset
));
1121 PP_ASSERT_WITH_CODE((0 < pp_table
->usStateArrayOffset
),
1122 "Invalid PowerPlay Table State Array Offset.", return -1);
1123 PP_ASSERT_WITH_CODE((0 < state_arrays
->ucNumEntries
),
1124 "Invalid PowerPlay Table State Array.", return -1);
1125 PP_ASSERT_WITH_CODE((entry_index
<= state_arrays
->ucNumEntries
),
1126 "Invalid PowerPlay Table State Array Entry.", return -1);
1128 state_entry
= &(state_arrays
->states
[entry_index
]);
1130 result
= call_back_func(hwmgr
, (void *)state_entry
, power_state
,
1132 make_classification_flags(hwmgr
,
1133 le16_to_cpu(state_entry
->usClassification
),
1134 le16_to_cpu(state_entry
->usClassification2
)));
1137 if (!result
&& (power_state
->classification
.flags
&
1138 PP_StateClassificationFlag_Boot
))
1139 result
= hwmgr
->hwmgr_func
->patch_boot_state(hwmgr
, &(power_state
->hardware
));