cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

process_pptables_v1_0.c (54223B)


      1/*
      2 * Copyright 2015 Advanced Micro Devices, Inc.
      3 *
      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:
     10 *
     11 * The above copyright notice and this permission notice shall be included in
     12 * all copies or substantial portions of the Software.
     13 *
     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.
     21 *
     22 */
     23#include "pp_debug.h"
     24#include <linux/module.h>
     25#include <linux/slab.h>
     26
     27#include "process_pptables_v1_0.h"
     28#include "ppatomctrl.h"
     29#include "atombios.h"
     30#include "hwmgr.h"
     31#include "cgs_common.h"
     32#include "pptable_v1_0.h"
     33
     34/**
     35 * set_hw_cap - Private Function used during initialization.
     36 * @hwmgr: Pointer to the hardware manager.
     37 * @setIt: A flag indication if the capability should be set (TRUE) or reset (FALSE).
     38 * @cap: Which capability to set/reset.
     39 */
     40static void set_hw_cap(struct pp_hwmgr *hwmgr, bool setIt, enum phm_platform_caps cap)
     41{
     42	if (setIt)
     43		phm_cap_set(hwmgr->platform_descriptor.platformCaps, cap);
     44	else
     45		phm_cap_unset(hwmgr->platform_descriptor.platformCaps, cap);
     46}
     47
     48
     49/**
     50 * set_platform_caps - Private Function used during initialization.
     51 * @hwmgr: Pointer to the hardware manager.
     52 * @powerplay_caps: the bit array (from BIOS) of capability bits.
     53 * Exception:  the current implementation always returns 1.
     54 */
     55static int set_platform_caps(struct pp_hwmgr *hwmgr, uint32_t powerplay_caps)
     56{
     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);
     67
     68	set_hw_cap(
     69			hwmgr,
     70			0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_POWERPLAY),
     71			PHM_PlatformCaps_PowerPlaySupport
     72		  );
     73
     74	set_hw_cap(
     75			hwmgr,
     76			0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_SBIOSPOWERSOURCE),
     77			PHM_PlatformCaps_BiosPowerSourceControl
     78		  );
     79
     80	set_hw_cap(
     81			hwmgr,
     82			0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_HARDWAREDC),
     83			PHM_PlatformCaps_AutomaticDCTransition
     84		  );
     85
     86	set_hw_cap(
     87			hwmgr,
     88			0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_MVDD_CONTROL),
     89			PHM_PlatformCaps_EnableMVDDControl
     90		  );
     91
     92	set_hw_cap(
     93			hwmgr,
     94			0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_VDDCI_CONTROL),
     95			PHM_PlatformCaps_ControlVDDCI
     96		  );
     97
     98	set_hw_cap(
     99			hwmgr,
    100			0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_VDDGFX_CONTROL),
    101			PHM_PlatformCaps_ControlVDDGFX
    102		  );
    103
    104	set_hw_cap(
    105			hwmgr,
    106			0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_BACO),
    107			PHM_PlatformCaps_BACO
    108		  );
    109
    110	set_hw_cap(
    111			hwmgr,
    112			0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_DISABLE_VOLTAGE_ISLAND),
    113			PHM_PlatformCaps_DisableVoltageIsland
    114		  );
    115
    116	set_hw_cap(
    117			hwmgr,
    118			0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_COMBINE_PCC_WITH_THERMAL_SIGNAL),
    119			PHM_PlatformCaps_CombinePCCWithThermalSignal
    120		  );
    121
    122	set_hw_cap(
    123			hwmgr,
    124			0 != (powerplay_caps & ATOM_TONGA_PLATFORM_LOAD_POST_PRODUCTION_FIRMWARE),
    125			PHM_PlatformCaps_LoadPostProductionFirmware
    126		  );
    127
    128	return 0;
    129}
    130
    131/*
    132 * Private Function to get the PowerPlay Table Address.
    133 */
    134static const void *get_powerplay_table(struct pp_hwmgr *hwmgr)
    135{
    136	int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
    137
    138	u16 size;
    139	u8 frev, crev;
    140	void *table_address = (void *)hwmgr->soft_pp_table;
    141
    142	if (!table_address) {
    143		table_address = (ATOM_Tonga_POWERPLAYTABLE *)
    144				smu_atom_get_data_table(hwmgr->adev,
    145						index, &size, &frev, &crev);
    146		hwmgr->soft_pp_table = table_address;	/*Cache the result in RAM.*/
    147		hwmgr->soft_pp_table_size = size;
    148	}
    149
    150	return table_address;
    151}
    152
    153static 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,
    157		uint32_t max_levels
    158		)
    159{
    160	uint32_t i;
    161	phm_ppt_v1_voltage_lookup_table *table;
    162	phm_ppt_v1_voltage_lookup_record *record;
    163	ATOM_Tonga_Voltage_Lookup_Record *atom_record;
    164
    165	PP_ASSERT_WITH_CODE((0 != vddc_lookup_pp_tables->ucNumEntries),
    166		"Invalid CAC Leakage PowerPlay Table!", return 1);
    167
    168	table = kzalloc(struct_size(table, entries, max_levels), GFP_KERNEL);
    169	if (!table)
    170		return -ENOMEM;
    171
    172	table->count = vddc_lookup_pp_tables->ucNumEntries;
    173
    174	for (i = 0; i < vddc_lookup_pp_tables->ucNumEntries; i++) {
    175		record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
    176					phm_ppt_v1_voltage_lookup_record,
    177					entries, table, i);
    178		atom_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
    179					ATOM_Tonga_Voltage_Lookup_Record,
    180					entries, vddc_lookup_pp_tables, i);
    181		record->us_calculated = 0;
    182		record->us_vdd = le16_to_cpu(atom_record->usVdd);
    183		record->us_cac_low = le16_to_cpu(atom_record->usCACLow);
    184		record->us_cac_mid = le16_to_cpu(atom_record->usCACMid);
    185		record->us_cac_high = le16_to_cpu(atom_record->usCACHigh);
    186	}
    187
    188	*lookup_table = table;
    189
    190	return 0;
    191}
    192
    193/**
    194 * get_platform_power_management_table - Private Function used during initialization.
    195 * Initialize Platform Power Management Parameter table
    196 * @hwmgr: Pointer to the hardware manager.
    197 * @atom_ppm_table: Pointer to PPM table in VBIOS
    198 */
    199static int get_platform_power_management_table(
    200		struct pp_hwmgr *hwmgr,
    201		ATOM_Tonga_PPM_Table *atom_ppm_table)
    202{
    203	struct phm_ppm_table *ptr = kzalloc(sizeof(ATOM_Tonga_PPM_Table), GFP_KERNEL);
    204	struct phm_ppt_v1_information *pp_table_information =
    205		(struct phm_ppt_v1_information *)(hwmgr->pptable);
    206
    207	if (NULL == ptr)
    208		return -ENOMEM;
    209
    210	ptr->ppm_design
    211		= atom_ppm_table->ucPpmDesign;
    212	ptr->cpu_core_number
    213		= le16_to_cpu(atom_ppm_table->usCpuCoreNumber);
    214	ptr->platform_tdp
    215		= le32_to_cpu(atom_ppm_table->ulPlatformTDP);
    216	ptr->small_ac_platform_tdp
    217		= le32_to_cpu(atom_ppm_table->ulSmallACPlatformTDP);
    218	ptr->platform_tdc
    219		= le32_to_cpu(atom_ppm_table->ulPlatformTDC);
    220	ptr->small_ac_platform_tdc
    221		= le32_to_cpu(atom_ppm_table->ulSmallACPlatformTDC);
    222	ptr->apu_tdp
    223		= le32_to_cpu(atom_ppm_table->ulApuTDP);
    224	ptr->dgpu_tdp
    225		= le32_to_cpu(atom_ppm_table->ulDGpuTDP);
    226	ptr->dgpu_ulv_power
    227		= le32_to_cpu(atom_ppm_table->ulDGpuUlvPower);
    228	ptr->tj_max
    229		= le32_to_cpu(atom_ppm_table->ulTjmax);
    230
    231	pp_table_information->ppm_parameter_table = ptr;
    232
    233	return 0;
    234}
    235
    236/**
    237 * init_dpm_2_parameters - Private Function used during initialization.
    238 * Initialize TDP limits for DPM2
    239 * @hwmgr: Pointer to the hardware manager.
    240 * @powerplay_table: Pointer to the PowerPlay Table.
    241 */
    242static int init_dpm_2_parameters(
    243		struct pp_hwmgr *hwmgr,
    244		const ATOM_Tonga_POWERPLAYTABLE *powerplay_table
    245		)
    246{
    247	int result = 0;
    248	struct phm_ppt_v1_information *pp_table_information = (struct phm_ppt_v1_information *)(hwmgr->pptable);
    249	ATOM_Tonga_PPM_Table *atom_ppm_table;
    250	uint32_t disable_ppm = 0;
    251	uint32_t disable_power_control = 0;
    252
    253	pp_table_information->us_ulv_voltage_offset =
    254		le16_to_cpu(powerplay_table->usUlvVoltageOffset);
    255
    256	pp_table_information->ppm_parameter_table = NULL;
    257	pp_table_information->vddc_lookup_table = NULL;
    258	pp_table_information->vddgfx_lookup_table = NULL;
    259	/* TDP limits */
    260	hwmgr->platform_descriptor.TDPODLimit =
    261		le16_to_cpu(powerplay_table->usPowerControlLimit);
    262	hwmgr->platform_descriptor.TDPAdjustment = 0;
    263	hwmgr->platform_descriptor.VidAdjustment = 0;
    264	hwmgr->platform_descriptor.VidAdjustmentPolarity = 0;
    265	hwmgr->platform_descriptor.VidMinLimit = 0;
    266	hwmgr->platform_descriptor.VidMaxLimit = 1500000;
    267	hwmgr->platform_descriptor.VidStep = 6250;
    268
    269	disable_power_control = 0;
    270	if (0 == disable_power_control) {
    271		/* enable TDP overdrive (PowerControl) feature as well if supported */
    272		if (hwmgr->platform_descriptor.TDPODLimit != 0)
    273			phm_cap_set(hwmgr->platform_descriptor.platformCaps,
    274			PHM_PlatformCaps_PowerControl);
    275	}
    276
    277	if (0 != powerplay_table->usVddcLookupTableOffset) {
    278		const ATOM_Tonga_Voltage_Lookup_Table *pVddcCACTable =
    279			(ATOM_Tonga_Voltage_Lookup_Table *)(((unsigned long)powerplay_table) +
    280			le16_to_cpu(powerplay_table->usVddcLookupTableOffset));
    281
    282		result = get_vddc_lookup_table(hwmgr,
    283			&pp_table_information->vddc_lookup_table, pVddcCACTable, 16);
    284	}
    285
    286	if (0 != powerplay_table->usVddgfxLookupTableOffset) {
    287		const ATOM_Tonga_Voltage_Lookup_Table *pVddgfxCACTable =
    288			(ATOM_Tonga_Voltage_Lookup_Table *)(((unsigned long)powerplay_table) +
    289			le16_to_cpu(powerplay_table->usVddgfxLookupTableOffset));
    290
    291		result = get_vddc_lookup_table(hwmgr,
    292			&pp_table_information->vddgfx_lookup_table, pVddgfxCACTable, 16);
    293	}
    294
    295	disable_ppm = 0;
    296	if (0 == disable_ppm) {
    297		atom_ppm_table = (ATOM_Tonga_PPM_Table *)
    298			(((unsigned long)powerplay_table) + le16_to_cpu(powerplay_table->usPPMTableOffset));
    299
    300		if (0 != powerplay_table->usPPMTableOffset) {
    301			if (get_platform_power_management_table(hwmgr, atom_ppm_table) == 0) {
    302				phm_cap_set(hwmgr->platform_descriptor.platformCaps,
    303					PHM_PlatformCaps_EnablePlatformPowerManagement);
    304			}
    305		}
    306	}
    307
    308	return result;
    309}
    310
    311static int get_valid_clk(
    312		struct pp_hwmgr *hwmgr,
    313		struct phm_clock_array **clk_table,
    314		phm_ppt_v1_clock_voltage_dependency_table const *clk_volt_pp_table
    315		)
    316{
    317	uint32_t i;
    318	struct phm_clock_array *table;
    319	phm_ppt_v1_clock_voltage_dependency_record *dep_record;
    320
    321	PP_ASSERT_WITH_CODE((0 != clk_volt_pp_table->count),
    322		"Invalid PowerPlay Table!", return -1);
    323
    324	table = kzalloc(struct_size(table, values, clk_volt_pp_table->count),
    325			GFP_KERNEL);
    326	if (!table)
    327		return -ENOMEM;
    328
    329	table->count = (uint32_t)clk_volt_pp_table->count;
    330
    331	for (i = 0; i < table->count; i++) {
    332		dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
    333				phm_ppt_v1_clock_voltage_dependency_record,
    334				entries, clk_volt_pp_table, i);
    335		table->values[i] = (uint32_t)dep_record->clk;
    336	}
    337	*clk_table = table;
    338
    339	return 0;
    340}
    341
    342static int get_hard_limits(
    343		struct pp_hwmgr *hwmgr,
    344		struct phm_clock_and_voltage_limits *limits,
    345		ATOM_Tonga_Hard_Limit_Table const *limitable
    346		)
    347{
    348	PP_ASSERT_WITH_CODE((0 != limitable->ucNumEntries), "Invalid PowerPlay Table!", return -1);
    349
    350	/* currently we always take entries[0] parameters */
    351	limits->sclk = le32_to_cpu(limitable->entries[0].ulSCLKLimit);
    352	limits->mclk = le32_to_cpu(limitable->entries[0].ulMCLKLimit);
    353	limits->vddc = le16_to_cpu(limitable->entries[0].usVddcLimit);
    354	limits->vddci = le16_to_cpu(limitable->entries[0].usVddciLimit);
    355	limits->vddgfx = le16_to_cpu(limitable->entries[0].usVddgfxLimit);
    356
    357	return 0;
    358}
    359
    360static int get_mclk_voltage_dependency_table(
    361		struct pp_hwmgr *hwmgr,
    362		phm_ppt_v1_clock_voltage_dependency_table **pp_tonga_mclk_dep_table,
    363		ATOM_Tonga_MCLK_Dependency_Table const *mclk_dep_table
    364		)
    365{
    366	uint32_t i;
    367	phm_ppt_v1_clock_voltage_dependency_table *mclk_table;
    368	phm_ppt_v1_clock_voltage_dependency_record *mclk_table_record;
    369	ATOM_Tonga_MCLK_Dependency_Record *mclk_dep_record;
    370
    371	PP_ASSERT_WITH_CODE((0 != mclk_dep_table->ucNumEntries),
    372		"Invalid PowerPlay Table!", return -1);
    373
    374	mclk_table = kzalloc(struct_size(mclk_table, entries, mclk_dep_table->ucNumEntries),
    375			     GFP_KERNEL);
    376	if (!mclk_table)
    377		return -ENOMEM;
    378
    379	mclk_table->count = (uint32_t)mclk_dep_table->ucNumEntries;
    380
    381	for (i = 0; i < mclk_dep_table->ucNumEntries; i++) {
    382		mclk_table_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
    383					phm_ppt_v1_clock_voltage_dependency_record,
    384						entries, mclk_table, i);
    385		mclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
    386					ATOM_Tonga_MCLK_Dependency_Record,
    387						entries, mclk_dep_table, i);
    388		mclk_table_record->vddInd = mclk_dep_record->ucVddcInd;
    389		mclk_table_record->vdd_offset = le16_to_cpu(mclk_dep_record->usVddgfxOffset);
    390		mclk_table_record->vddci = le16_to_cpu(mclk_dep_record->usVddci);
    391		mclk_table_record->mvdd = le16_to_cpu(mclk_dep_record->usMvdd);
    392		mclk_table_record->clk = le32_to_cpu(mclk_dep_record->ulMclk);
    393	}
    394
    395	*pp_tonga_mclk_dep_table = mclk_table;
    396
    397	return 0;
    398}
    399
    400static int get_sclk_voltage_dependency_table(
    401		struct pp_hwmgr *hwmgr,
    402		phm_ppt_v1_clock_voltage_dependency_table **pp_tonga_sclk_dep_table,
    403		PPTable_Generic_SubTable_Header const  *sclk_dep_table
    404		)
    405{
    406	uint32_t i;
    407	phm_ppt_v1_clock_voltage_dependency_table *sclk_table;
    408	phm_ppt_v1_clock_voltage_dependency_record *sclk_table_record;
    409
    410	if (sclk_dep_table->ucRevId < 1) {
    411		const ATOM_Tonga_SCLK_Dependency_Table *tonga_table =
    412			    (ATOM_Tonga_SCLK_Dependency_Table *)sclk_dep_table;
    413		ATOM_Tonga_SCLK_Dependency_Record *sclk_dep_record;
    414
    415		PP_ASSERT_WITH_CODE((0 != tonga_table->ucNumEntries),
    416			"Invalid PowerPlay Table!", return -1);
    417
    418		sclk_table = kzalloc(struct_size(sclk_table, entries, tonga_table->ucNumEntries),
    419				     GFP_KERNEL);
    420		if (!sclk_table)
    421			return -ENOMEM;
    422
    423		sclk_table->count = (uint32_t)tonga_table->ucNumEntries;
    424
    425		for (i = 0; i < tonga_table->ucNumEntries; i++) {
    426			sclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
    427						ATOM_Tonga_SCLK_Dependency_Record,
    428						entries, tonga_table, i);
    429			sclk_table_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
    430						phm_ppt_v1_clock_voltage_dependency_record,
    431						entries, sclk_table, i);
    432			sclk_table_record->vddInd = sclk_dep_record->ucVddInd;
    433			sclk_table_record->vdd_offset = le16_to_cpu(sclk_dep_record->usVddcOffset);
    434			sclk_table_record->clk = le32_to_cpu(sclk_dep_record->ulSclk);
    435			sclk_table_record->cks_enable =
    436				(((sclk_dep_record->ucCKSVOffsetandDisable & 0x80) >> 7) == 0) ? 1 : 0;
    437			sclk_table_record->cks_voffset = (sclk_dep_record->ucCKSVOffsetandDisable & 0x7F);
    438		}
    439	} else {
    440		const ATOM_Polaris_SCLK_Dependency_Table *polaris_table =
    441			    (ATOM_Polaris_SCLK_Dependency_Table *)sclk_dep_table;
    442		ATOM_Polaris_SCLK_Dependency_Record *sclk_dep_record;
    443
    444		PP_ASSERT_WITH_CODE((0 != polaris_table->ucNumEntries),
    445			"Invalid PowerPlay Table!", return -1);
    446
    447		sclk_table = kzalloc(struct_size(sclk_table, entries, polaris_table->ucNumEntries),
    448				     GFP_KERNEL);
    449		if (!sclk_table)
    450			return -ENOMEM;
    451
    452		sclk_table->count = (uint32_t)polaris_table->ucNumEntries;
    453
    454		for (i = 0; i < polaris_table->ucNumEntries; i++) {
    455			sclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
    456						ATOM_Polaris_SCLK_Dependency_Record,
    457						entries, polaris_table, i);
    458			sclk_table_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
    459						phm_ppt_v1_clock_voltage_dependency_record,
    460						entries, sclk_table, i);
    461			sclk_table_record->vddInd = sclk_dep_record->ucVddInd;
    462			sclk_table_record->vdd_offset = le16_to_cpu(sclk_dep_record->usVddcOffset);
    463			sclk_table_record->clk = le32_to_cpu(sclk_dep_record->ulSclk);
    464			sclk_table_record->cks_enable =
    465				(((sclk_dep_record->ucCKSVOffsetandDisable & 0x80) >> 7) == 0) ? 1 : 0;
    466			sclk_table_record->cks_voffset = (sclk_dep_record->ucCKSVOffsetandDisable & 0x7F);
    467			sclk_table_record->sclk_offset = le32_to_cpu(sclk_dep_record->ulSclkOffset);
    468		}
    469	}
    470	*pp_tonga_sclk_dep_table = sclk_table;
    471
    472	return 0;
    473}
    474
    475static int get_pcie_table(
    476		struct pp_hwmgr *hwmgr,
    477		phm_ppt_v1_pcie_table **pp_tonga_pcie_table,
    478		PPTable_Generic_SubTable_Header const *ptable
    479		)
    480{
    481	uint32_t i, pcie_count;
    482	phm_ppt_v1_pcie_table *pcie_table;
    483	struct phm_ppt_v1_information *pp_table_information =
    484		(struct phm_ppt_v1_information *)(hwmgr->pptable);
    485	phm_ppt_v1_pcie_record *pcie_record;
    486
    487	if (ptable->ucRevId < 1) {
    488		const ATOM_Tonga_PCIE_Table *atom_pcie_table = (ATOM_Tonga_PCIE_Table *)ptable;
    489		ATOM_Tonga_PCIE_Record *atom_pcie_record;
    490
    491		PP_ASSERT_WITH_CODE((atom_pcie_table->ucNumEntries != 0),
    492			"Invalid PowerPlay Table!", return -1);
    493
    494		pcie_table = kzalloc(struct_size(pcie_table, entries,
    495						 atom_pcie_table->ucNumEntries),
    496				     GFP_KERNEL);
    497		if (!pcie_table)
    498			return -ENOMEM;
    499
    500		/*
    501		* Make sure the number of pcie entries are less than or equal to sclk dpm levels.
    502		* Since first PCIE entry is for ULV, #pcie has to be <= SclkLevel + 1.
    503		*/
    504		pcie_count = (pp_table_information->vdd_dep_on_sclk->count) + 1;
    505		if ((uint32_t)atom_pcie_table->ucNumEntries <= pcie_count)
    506			pcie_count = (uint32_t)atom_pcie_table->ucNumEntries;
    507		else
    508			pr_err("Number of Pcie Entries exceed the number of SCLK Dpm Levels! Disregarding the excess entries...\n");
    509
    510		pcie_table->count = pcie_count;
    511		for (i = 0; i < pcie_count; i++) {
    512			pcie_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
    513						phm_ppt_v1_pcie_record,
    514						entries, pcie_table, i);
    515			atom_pcie_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
    516						ATOM_Tonga_PCIE_Record,
    517						entries, atom_pcie_table, i);
    518			pcie_record->gen_speed = atom_pcie_record->ucPCIEGenSpeed;
    519			pcie_record->lane_width = le16_to_cpu(atom_pcie_record->usPCIELaneWidth);
    520		}
    521
    522		*pp_tonga_pcie_table = pcie_table;
    523	} else {
    524		/* Polaris10/Polaris11 and newer. */
    525		const ATOM_Polaris10_PCIE_Table *atom_pcie_table = (ATOM_Polaris10_PCIE_Table *)ptable;
    526		ATOM_Polaris10_PCIE_Record *atom_pcie_record;
    527
    528		PP_ASSERT_WITH_CODE((atom_pcie_table->ucNumEntries != 0),
    529			"Invalid PowerPlay Table!", return -1);
    530
    531		pcie_table = kzalloc(struct_size(pcie_table, entries,
    532						 atom_pcie_table->ucNumEntries),
    533				     GFP_KERNEL);
    534		if (!pcie_table)
    535			return -ENOMEM;
    536
    537		/*
    538		* Make sure the number of pcie entries are less than or equal to sclk dpm levels.
    539		* Since first PCIE entry is for ULV, #pcie has to be <= SclkLevel + 1.
    540		*/
    541		pcie_count = (pp_table_information->vdd_dep_on_sclk->count) + 1;
    542		if ((uint32_t)atom_pcie_table->ucNumEntries <= pcie_count)
    543			pcie_count = (uint32_t)atom_pcie_table->ucNumEntries;
    544		else
    545			pr_err("Number of Pcie Entries exceed the number of SCLK Dpm Levels! Disregarding the excess entries...\n");
    546
    547		pcie_table->count = pcie_count;
    548
    549		for (i = 0; i < pcie_count; i++) {
    550			pcie_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
    551						phm_ppt_v1_pcie_record,
    552						entries, pcie_table, i);
    553			atom_pcie_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
    554						ATOM_Polaris10_PCIE_Record,
    555						entries, atom_pcie_table, i);
    556			pcie_record->gen_speed = atom_pcie_record->ucPCIEGenSpeed;
    557			pcie_record->lane_width = le16_to_cpu(atom_pcie_record->usPCIELaneWidth);
    558			pcie_record->pcie_sclk = le32_to_cpu(atom_pcie_record->ulPCIE_Sclk);
    559		}
    560
    561		*pp_tonga_pcie_table = pcie_table;
    562	}
    563
    564	return 0;
    565}
    566
    567static int get_cac_tdp_table(
    568		struct pp_hwmgr *hwmgr,
    569		struct phm_cac_tdp_table **cac_tdp_table,
    570		const PPTable_Generic_SubTable_Header * table
    571		)
    572{
    573	uint32_t table_size;
    574	struct phm_cac_tdp_table *tdp_table;
    575
    576	table_size = sizeof(uint32_t) + sizeof(struct phm_cac_tdp_table);
    577	tdp_table = kzalloc(table_size, GFP_KERNEL);
    578
    579	if (NULL == tdp_table)
    580		return -ENOMEM;
    581
    582	hwmgr->dyn_state.cac_dtp_table = kzalloc(table_size, GFP_KERNEL);
    583
    584	if (NULL == hwmgr->dyn_state.cac_dtp_table) {
    585		kfree(tdp_table);
    586		return -ENOMEM;
    587	}
    588
    589	if (table->ucRevId < 3) {
    590		const ATOM_Tonga_PowerTune_Table *tonga_table =
    591			(ATOM_Tonga_PowerTune_Table *)table;
    592		tdp_table->usTDP = le16_to_cpu(tonga_table->usTDP);
    593		tdp_table->usConfigurableTDP =
    594			le16_to_cpu(tonga_table->usConfigurableTDP);
    595		tdp_table->usTDC = le16_to_cpu(tonga_table->usTDC);
    596		tdp_table->usBatteryPowerLimit =
    597			le16_to_cpu(tonga_table->usBatteryPowerLimit);
    598		tdp_table->usSmallPowerLimit =
    599			le16_to_cpu(tonga_table->usSmallPowerLimit);
    600		tdp_table->usLowCACLeakage =
    601			le16_to_cpu(tonga_table->usLowCACLeakage);
    602		tdp_table->usHighCACLeakage =
    603			le16_to_cpu(tonga_table->usHighCACLeakage);
    604		tdp_table->usMaximumPowerDeliveryLimit =
    605			le16_to_cpu(tonga_table->usMaximumPowerDeliveryLimit);
    606		tdp_table->usDefaultTargetOperatingTemp =
    607			le16_to_cpu(tonga_table->usTjMax);
    608		tdp_table->usTargetOperatingTemp =
    609			le16_to_cpu(tonga_table->usTjMax); /*Set the initial temp to the same as default */
    610		tdp_table->usPowerTuneDataSetID =
    611			le16_to_cpu(tonga_table->usPowerTuneDataSetID);
    612		tdp_table->usSoftwareShutdownTemp =
    613			le16_to_cpu(tonga_table->usSoftwareShutdownTemp);
    614		tdp_table->usClockStretchAmount =
    615			le16_to_cpu(tonga_table->usClockStretchAmount);
    616	} else if (table->ucRevId < 4) {   /* Fiji and newer */
    617		const ATOM_Fiji_PowerTune_Table *fijitable =
    618			(ATOM_Fiji_PowerTune_Table *)table;
    619		tdp_table->usTDP = le16_to_cpu(fijitable->usTDP);
    620		tdp_table->usConfigurableTDP = le16_to_cpu(fijitable->usConfigurableTDP);
    621		tdp_table->usTDC = le16_to_cpu(fijitable->usTDC);
    622		tdp_table->usBatteryPowerLimit = le16_to_cpu(fijitable->usBatteryPowerLimit);
    623		tdp_table->usSmallPowerLimit = le16_to_cpu(fijitable->usSmallPowerLimit);
    624		tdp_table->usLowCACLeakage = le16_to_cpu(fijitable->usLowCACLeakage);
    625		tdp_table->usHighCACLeakage = le16_to_cpu(fijitable->usHighCACLeakage);
    626		tdp_table->usMaximumPowerDeliveryLimit =
    627			le16_to_cpu(fijitable->usMaximumPowerDeliveryLimit);
    628		tdp_table->usDefaultTargetOperatingTemp =
    629			le16_to_cpu(fijitable->usTjMax);
    630		tdp_table->usTargetOperatingTemp =
    631			le16_to_cpu(fijitable->usTjMax); /*Set the initial temp to the same as default */
    632		tdp_table->usPowerTuneDataSetID =
    633			le16_to_cpu(fijitable->usPowerTuneDataSetID);
    634		tdp_table->usSoftwareShutdownTemp =
    635			le16_to_cpu(fijitable->usSoftwareShutdownTemp);
    636		tdp_table->usClockStretchAmount =
    637			le16_to_cpu(fijitable->usClockStretchAmount);
    638		tdp_table->usTemperatureLimitHotspot =
    639			le16_to_cpu(fijitable->usTemperatureLimitHotspot);
    640		tdp_table->usTemperatureLimitLiquid1 =
    641			le16_to_cpu(fijitable->usTemperatureLimitLiquid1);
    642		tdp_table->usTemperatureLimitLiquid2 =
    643			le16_to_cpu(fijitable->usTemperatureLimitLiquid2);
    644		tdp_table->usTemperatureLimitVrVddc =
    645			le16_to_cpu(fijitable->usTemperatureLimitVrVddc);
    646		tdp_table->usTemperatureLimitVrMvdd =
    647			le16_to_cpu(fijitable->usTemperatureLimitVrMvdd);
    648		tdp_table->usTemperatureLimitPlx =
    649			le16_to_cpu(fijitable->usTemperatureLimitPlx);
    650		tdp_table->ucLiquid1_I2C_address =
    651			fijitable->ucLiquid1_I2C_address;
    652		tdp_table->ucLiquid2_I2C_address =
    653			fijitable->ucLiquid2_I2C_address;
    654		tdp_table->ucLiquid_I2C_Line =
    655			fijitable->ucLiquid_I2C_Line;
    656		tdp_table->ucVr_I2C_address = fijitable->ucVr_I2C_address;
    657		tdp_table->ucVr_I2C_Line = fijitable->ucVr_I2C_Line;
    658		tdp_table->ucPlx_I2C_address = fijitable->ucPlx_I2C_address;
    659		tdp_table->ucPlx_I2C_Line = fijitable->ucPlx_I2C_Line;
    660	} else {
    661		const ATOM_Polaris_PowerTune_Table *polaristable =
    662			(ATOM_Polaris_PowerTune_Table *)table;
    663		tdp_table->usTDP = le16_to_cpu(polaristable->usTDP);
    664		tdp_table->usConfigurableTDP = le16_to_cpu(polaristable->usConfigurableTDP);
    665		tdp_table->usTDC = le16_to_cpu(polaristable->usTDC);
    666		tdp_table->usBatteryPowerLimit = le16_to_cpu(polaristable->usBatteryPowerLimit);
    667		tdp_table->usSmallPowerLimit = le16_to_cpu(polaristable->usSmallPowerLimit);
    668		tdp_table->usLowCACLeakage = le16_to_cpu(polaristable->usLowCACLeakage);
    669		tdp_table->usHighCACLeakage = le16_to_cpu(polaristable->usHighCACLeakage);
    670		tdp_table->usMaximumPowerDeliveryLimit =
    671			le16_to_cpu(polaristable->usMaximumPowerDeliveryLimit);
    672		tdp_table->usDefaultTargetOperatingTemp =
    673			le16_to_cpu(polaristable->usTjMax);
    674		tdp_table->usTargetOperatingTemp =
    675			le16_to_cpu(polaristable->usTjMax); /*Set the initial temp to the same as default */
    676		tdp_table->usPowerTuneDataSetID =
    677			le16_to_cpu(polaristable->usPowerTuneDataSetID);
    678		tdp_table->usSoftwareShutdownTemp =
    679			le16_to_cpu(polaristable->usSoftwareShutdownTemp);
    680		tdp_table->usClockStretchAmount =
    681			le16_to_cpu(polaristable->usClockStretchAmount);
    682		tdp_table->usTemperatureLimitHotspot =
    683			le16_to_cpu(polaristable->usTemperatureLimitHotspot);
    684		tdp_table->usTemperatureLimitLiquid1 =
    685			le16_to_cpu(polaristable->usTemperatureLimitLiquid1);
    686		tdp_table->usTemperatureLimitLiquid2 =
    687			le16_to_cpu(polaristable->usTemperatureLimitLiquid2);
    688		tdp_table->usTemperatureLimitVrVddc =
    689			le16_to_cpu(polaristable->usTemperatureLimitVrVddc);
    690		tdp_table->usTemperatureLimitVrMvdd =
    691			le16_to_cpu(polaristable->usTemperatureLimitVrMvdd);
    692		tdp_table->usTemperatureLimitPlx =
    693			le16_to_cpu(polaristable->usTemperatureLimitPlx);
    694		tdp_table->ucLiquid1_I2C_address =
    695			polaristable->ucLiquid1_I2C_address;
    696		tdp_table->ucLiquid2_I2C_address =
    697			polaristable->ucLiquid2_I2C_address;
    698		tdp_table->ucLiquid_I2C_Line =
    699			polaristable->ucLiquid_I2C_Line;
    700		tdp_table->ucVr_I2C_address = polaristable->ucVr_I2C_address;
    701		tdp_table->ucVr_I2C_Line = polaristable->ucVr_I2C_Line;
    702		tdp_table->ucPlx_I2C_address = polaristable->ucPlx_I2C_address;
    703		tdp_table->ucPlx_I2C_Line = polaristable->ucPlx_I2C_Line;
    704		tdp_table->usBoostPowerLimit = polaristable->usBoostPowerLimit;
    705		tdp_table->ucCKS_LDO_REFSEL = polaristable->ucCKS_LDO_REFSEL;
    706		tdp_table->ucHotSpotOnly = polaristable->ucHotSpotOnly;
    707	}
    708
    709	*cac_tdp_table = tdp_table;
    710
    711	return 0;
    712}
    713
    714static int get_mm_clock_voltage_table(
    715		struct pp_hwmgr *hwmgr,
    716		phm_ppt_v1_mm_clock_voltage_dependency_table **tonga_mm_table,
    717		const ATOM_Tonga_MM_Dependency_Table * mm_dependency_table
    718		)
    719{
    720	uint32_t i;
    721	const ATOM_Tonga_MM_Dependency_Record *mm_dependency_record;
    722	phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table;
    723	phm_ppt_v1_mm_clock_voltage_dependency_record *mm_table_record;
    724
    725	PP_ASSERT_WITH_CODE((0 != mm_dependency_table->ucNumEntries),
    726		"Invalid PowerPlay Table!", return -1);
    727	mm_table = kzalloc(struct_size(mm_table, entries, mm_dependency_table->ucNumEntries),
    728			   GFP_KERNEL);
    729	if (!mm_table)
    730		return -ENOMEM;
    731
    732	mm_table->count = mm_dependency_table->ucNumEntries;
    733
    734	for (i = 0; i < mm_dependency_table->ucNumEntries; i++) {
    735		mm_dependency_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
    736						ATOM_Tonga_MM_Dependency_Record,
    737						entries, mm_dependency_table, i);
    738		mm_table_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
    739					phm_ppt_v1_mm_clock_voltage_dependency_record,
    740					entries, mm_table, i);
    741		mm_table_record->vddcInd = mm_dependency_record->ucVddcInd;
    742		mm_table_record->vddgfx_offset = le16_to_cpu(mm_dependency_record->usVddgfxOffset);
    743		mm_table_record->aclk = le32_to_cpu(mm_dependency_record->ulAClk);
    744		mm_table_record->samclock = le32_to_cpu(mm_dependency_record->ulSAMUClk);
    745		mm_table_record->eclk = le32_to_cpu(mm_dependency_record->ulEClk);
    746		mm_table_record->vclk = le32_to_cpu(mm_dependency_record->ulVClk);
    747		mm_table_record->dclk = le32_to_cpu(mm_dependency_record->ulDClk);
    748	}
    749
    750	*tonga_mm_table = mm_table;
    751
    752	return 0;
    753}
    754
    755static int get_gpio_table(struct pp_hwmgr *hwmgr,
    756		struct phm_ppt_v1_gpio_table **pp_tonga_gpio_table,
    757		const ATOM_Tonga_GPIO_Table *atom_gpio_table)
    758{
    759	uint32_t table_size;
    760	struct phm_ppt_v1_gpio_table *pp_gpio_table;
    761	struct phm_ppt_v1_information *pp_table_information =
    762			(struct phm_ppt_v1_information *)(hwmgr->pptable);
    763
    764	table_size = sizeof(struct phm_ppt_v1_gpio_table);
    765	pp_gpio_table = kzalloc(table_size, GFP_KERNEL);
    766	if (!pp_gpio_table)
    767		return -ENOMEM;
    768
    769	if (pp_table_information->vdd_dep_on_sclk->count <
    770			atom_gpio_table->ucVRHotTriggeredSclkDpmIndex)
    771		PP_ASSERT_WITH_CODE(false,
    772				"SCLK DPM index for VRHot cannot exceed the total sclk level count!",);
    773	else
    774		pp_gpio_table->vrhot_triggered_sclk_dpm_index =
    775				atom_gpio_table->ucVRHotTriggeredSclkDpmIndex;
    776
    777	*pp_tonga_gpio_table = pp_gpio_table;
    778
    779	return 0;
    780}
    781/**
    782 * init_clock_voltage_dependency - Private Function used during initialization.
    783 * Initialize clock voltage dependency
    784 * @hwmgr: Pointer to the hardware manager.
    785 * @powerplay_table: Pointer to the PowerPlay Table.
    786 */
    787static int init_clock_voltage_dependency(
    788		struct pp_hwmgr *hwmgr,
    789		const ATOM_Tonga_POWERPLAYTABLE *powerplay_table
    790		)
    791{
    792	int result = 0;
    793	struct phm_ppt_v1_information *pp_table_information =
    794		(struct phm_ppt_v1_information *)(hwmgr->pptable);
    795
    796	const ATOM_Tonga_MM_Dependency_Table *mm_dependency_table =
    797		(const ATOM_Tonga_MM_Dependency_Table *)(((unsigned long) powerplay_table) +
    798		le16_to_cpu(powerplay_table->usMMDependencyTableOffset));
    799	const PPTable_Generic_SubTable_Header *pPowerTuneTable =
    800		(const PPTable_Generic_SubTable_Header *)(((unsigned long) powerplay_table) +
    801		le16_to_cpu(powerplay_table->usPowerTuneTableOffset));
    802	const ATOM_Tonga_MCLK_Dependency_Table *mclk_dep_table =
    803		(const ATOM_Tonga_MCLK_Dependency_Table *)(((unsigned long) powerplay_table) +
    804		le16_to_cpu(powerplay_table->usMclkDependencyTableOffset));
    805	const PPTable_Generic_SubTable_Header *sclk_dep_table =
    806		(const PPTable_Generic_SubTable_Header *)(((unsigned long) powerplay_table) +
    807		le16_to_cpu(powerplay_table->usSclkDependencyTableOffset));
    808	const ATOM_Tonga_Hard_Limit_Table *pHardLimits =
    809		(const ATOM_Tonga_Hard_Limit_Table *)(((unsigned long) powerplay_table) +
    810		le16_to_cpu(powerplay_table->usHardLimitTableOffset));
    811	const PPTable_Generic_SubTable_Header *pcie_table =
    812		(const PPTable_Generic_SubTable_Header *)(((unsigned long) powerplay_table) +
    813		le16_to_cpu(powerplay_table->usPCIETableOffset));
    814	const ATOM_Tonga_GPIO_Table *gpio_table =
    815		(const ATOM_Tonga_GPIO_Table *)(((unsigned long) powerplay_table) +
    816		le16_to_cpu(powerplay_table->usGPIOTableOffset));
    817
    818	pp_table_information->vdd_dep_on_sclk = NULL;
    819	pp_table_information->vdd_dep_on_mclk = NULL;
    820	pp_table_information->mm_dep_table = NULL;
    821	pp_table_information->pcie_table = NULL;
    822	pp_table_information->gpio_table = NULL;
    823
    824	if (powerplay_table->usMMDependencyTableOffset != 0)
    825		result = get_mm_clock_voltage_table(hwmgr,
    826		&pp_table_information->mm_dep_table, mm_dependency_table);
    827
    828	if (result == 0 && powerplay_table->usPowerTuneTableOffset != 0)
    829		result = get_cac_tdp_table(hwmgr,
    830		&pp_table_information->cac_dtp_table, pPowerTuneTable);
    831
    832	if (result == 0 && powerplay_table->usSclkDependencyTableOffset != 0)
    833		result = get_sclk_voltage_dependency_table(hwmgr,
    834		&pp_table_information->vdd_dep_on_sclk, sclk_dep_table);
    835
    836	if (result == 0 && powerplay_table->usMclkDependencyTableOffset != 0)
    837		result = get_mclk_voltage_dependency_table(hwmgr,
    838		&pp_table_information->vdd_dep_on_mclk, mclk_dep_table);
    839
    840	if (result == 0 && powerplay_table->usPCIETableOffset != 0)
    841		result = get_pcie_table(hwmgr,
    842		&pp_table_information->pcie_table, pcie_table);
    843
    844	if (result == 0 && powerplay_table->usHardLimitTableOffset != 0)
    845		result = get_hard_limits(hwmgr,
    846		&pp_table_information->max_clock_voltage_on_dc, pHardLimits);
    847
    848	hwmgr->dyn_state.max_clock_voltage_on_dc.sclk =
    849		pp_table_information->max_clock_voltage_on_dc.sclk;
    850	hwmgr->dyn_state.max_clock_voltage_on_dc.mclk =
    851		pp_table_information->max_clock_voltage_on_dc.mclk;
    852	hwmgr->dyn_state.max_clock_voltage_on_dc.vddc =
    853		pp_table_information->max_clock_voltage_on_dc.vddc;
    854	hwmgr->dyn_state.max_clock_voltage_on_dc.vddci =
    855		pp_table_information->max_clock_voltage_on_dc.vddci;
    856
    857	if (result == 0 && (NULL != pp_table_information->vdd_dep_on_mclk)
    858		&& (0 != pp_table_information->vdd_dep_on_mclk->count))
    859		result = get_valid_clk(hwmgr, &pp_table_information->valid_mclk_values,
    860		pp_table_information->vdd_dep_on_mclk);
    861
    862	if (result == 0 && (NULL != pp_table_information->vdd_dep_on_sclk)
    863		&& (0 != pp_table_information->vdd_dep_on_sclk->count))
    864		result = get_valid_clk(hwmgr, &pp_table_information->valid_sclk_values,
    865		pp_table_information->vdd_dep_on_sclk);
    866
    867	if (!result && gpio_table)
    868		result = get_gpio_table(hwmgr, &pp_table_information->gpio_table,
    869				gpio_table);
    870
    871	return result;
    872}
    873
    874/**
    875 * init_over_drive_limits - Retrieves the (signed) Overdrive limits from VBIOS.
    876 * The max engine clock, memory clock and max temperature come from the firmware info table.
    877 *
    878 * The information is placed into the platform descriptor.
    879 *
    880 * @hwmgr: source of the VBIOS table and owner of the platform descriptor to be updated.
    881 * @powerplay_table: the address of the PowerPlay table.
    882 *
    883 * Return: 1 as long as the firmware info table was present and of a supported version.
    884 */
    885static int init_over_drive_limits(
    886		struct pp_hwmgr *hwmgr,
    887		const ATOM_Tonga_POWERPLAYTABLE *powerplay_table)
    888{
    889	hwmgr->platform_descriptor.overdriveLimit.engineClock =
    890		le32_to_cpu(powerplay_table->ulMaxODEngineClock);
    891	hwmgr->platform_descriptor.overdriveLimit.memoryClock =
    892		le32_to_cpu(powerplay_table->ulMaxODMemoryClock);
    893
    894	hwmgr->platform_descriptor.minOverdriveVDDC = 0;
    895	hwmgr->platform_descriptor.maxOverdriveVDDC = 0;
    896	hwmgr->platform_descriptor.overdriveVDDCStep = 0;
    897
    898	return 0;
    899}
    900
    901/**
    902 * init_thermal_controller - Private Function used during initialization.
    903 * Inspect the PowerPlay table for obvious signs of corruption.
    904 * @hwmgr: Pointer to the hardware manager.
    905 * @powerplay_table: Pointer to the PowerPlay Table.
    906 * Exception:  This implementation always returns 1.
    907 */
    908static int init_thermal_controller(
    909		struct pp_hwmgr *hwmgr,
    910		const ATOM_Tonga_POWERPLAYTABLE *powerplay_table
    911		)
    912{
    913	const PPTable_Generic_SubTable_Header *fan_table;
    914	ATOM_Tonga_Thermal_Controller *thermal_controller;
    915
    916	thermal_controller = (ATOM_Tonga_Thermal_Controller *)
    917		(((unsigned long)powerplay_table) +
    918		le16_to_cpu(powerplay_table->usThermalControllerOffset));
    919	PP_ASSERT_WITH_CODE((0 != powerplay_table->usThermalControllerOffset),
    920		"Thermal controller table not set!", return -1);
    921
    922	hwmgr->thermal_controller.ucType = thermal_controller->ucType;
    923	hwmgr->thermal_controller.ucI2cLine = thermal_controller->ucI2cLine;
    924	hwmgr->thermal_controller.ucI2cAddress = thermal_controller->ucI2cAddress;
    925
    926	hwmgr->thermal_controller.fanInfo.bNoFan =
    927		(0 != (thermal_controller->ucFanParameters & ATOM_TONGA_PP_FANPARAMETERS_NOFAN));
    928
    929	hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution =
    930		thermal_controller->ucFanParameters &
    931		ATOM_TONGA_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK;
    932
    933	hwmgr->thermal_controller.fanInfo.ulMinRPM
    934		= thermal_controller->ucFanMinRPM * 100UL;
    935	hwmgr->thermal_controller.fanInfo.ulMaxRPM
    936		= thermal_controller->ucFanMaxRPM * 100UL;
    937
    938	set_hw_cap(
    939			hwmgr,
    940			ATOM_TONGA_PP_THERMALCONTROLLER_NONE != hwmgr->thermal_controller.ucType,
    941			PHM_PlatformCaps_ThermalController
    942		  );
    943
    944	if (0 == powerplay_table->usFanTableOffset) {
    945		hwmgr->thermal_controller.use_hw_fan_control = 1;
    946		return 0;
    947	}
    948
    949	fan_table = (const PPTable_Generic_SubTable_Header *)
    950		(((unsigned long)powerplay_table) +
    951		le16_to_cpu(powerplay_table->usFanTableOffset));
    952
    953	PP_ASSERT_WITH_CODE((0 != powerplay_table->usFanTableOffset),
    954		"Fan table not set!", return -1);
    955	PP_ASSERT_WITH_CODE((0 < fan_table->ucRevId),
    956		"Unsupported fan table format!", return -1);
    957
    958	hwmgr->thermal_controller.advanceFanControlParameters.ulCycleDelay
    959		= 100000;
    960	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
    961		PHM_PlatformCaps_MicrocodeFanControl);
    962
    963	if (fan_table->ucRevId < 8) {
    964		const ATOM_Tonga_Fan_Table *tonga_fan_table =
    965			(ATOM_Tonga_Fan_Table *)fan_table;
    966		hwmgr->thermal_controller.advanceFanControlParameters.ucTHyst
    967			= tonga_fan_table->ucTHyst;
    968		hwmgr->thermal_controller.advanceFanControlParameters.usTMin
    969			= le16_to_cpu(tonga_fan_table->usTMin);
    970		hwmgr->thermal_controller.advanceFanControlParameters.usTMed
    971			= le16_to_cpu(tonga_fan_table->usTMed);
    972		hwmgr->thermal_controller.advanceFanControlParameters.usTHigh
    973			= le16_to_cpu(tonga_fan_table->usTHigh);
    974		hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin
    975			= le16_to_cpu(tonga_fan_table->usPWMMin);
    976		hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed
    977			= le16_to_cpu(tonga_fan_table->usPWMMed);
    978		hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh
    979			= le16_to_cpu(tonga_fan_table->usPWMHigh);
    980		hwmgr->thermal_controller.advanceFanControlParameters.usTMax
    981			= 10900;                  /* hard coded */
    982		hwmgr->thermal_controller.advanceFanControlParameters.usTMax
    983			= le16_to_cpu(tonga_fan_table->usTMax);
    984		hwmgr->thermal_controller.advanceFanControlParameters.ucFanControlMode
    985			= tonga_fan_table->ucFanControlMode;
    986		hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanPWM
    987			= le16_to_cpu(tonga_fan_table->usFanPWMMax);
    988		hwmgr->thermal_controller.advanceFanControlParameters.usDefaultFanOutputSensitivity
    989			= 4836;
    990		hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity
    991			= le16_to_cpu(tonga_fan_table->usFanOutputSensitivity);
    992		hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanRPM
    993			= le16_to_cpu(tonga_fan_table->usFanRPMMax);
    994		hwmgr->thermal_controller.advanceFanControlParameters.ulMinFanSCLKAcousticLimit
    995			= (le32_to_cpu(tonga_fan_table->ulMinFanSCLKAcousticLimit) / 100); /* PPTable stores it in 10Khz unit for 2 decimal places.  SMC wants MHz. */
    996		hwmgr->thermal_controller.advanceFanControlParameters.ucTargetTemperature
    997			= tonga_fan_table->ucTargetTemperature;
    998		hwmgr->thermal_controller.advanceFanControlParameters.ucMinimumPWMLimit
    999			= tonga_fan_table->ucMinimumPWMLimit;
   1000	} else if (fan_table->ucRevId == 8) {
   1001		const ATOM_Fiji_Fan_Table *fiji_fan_table =
   1002			(ATOM_Fiji_Fan_Table *)fan_table;
   1003		hwmgr->thermal_controller.advanceFanControlParameters.ucTHyst
   1004			= fiji_fan_table->ucTHyst;
   1005		hwmgr->thermal_controller.advanceFanControlParameters.usTMin
   1006			= le16_to_cpu(fiji_fan_table->usTMin);
   1007		hwmgr->thermal_controller.advanceFanControlParameters.usTMed
   1008			= le16_to_cpu(fiji_fan_table->usTMed);
   1009		hwmgr->thermal_controller.advanceFanControlParameters.usTHigh
   1010			= le16_to_cpu(fiji_fan_table->usTHigh);
   1011		hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin
   1012			= le16_to_cpu(fiji_fan_table->usPWMMin);
   1013		hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed
   1014			= le16_to_cpu(fiji_fan_table->usPWMMed);
   1015		hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh
   1016			= le16_to_cpu(fiji_fan_table->usPWMHigh);
   1017		hwmgr->thermal_controller.advanceFanControlParameters.usTMax
   1018			= le16_to_cpu(fiji_fan_table->usTMax);
   1019		hwmgr->thermal_controller.advanceFanControlParameters.ucFanControlMode
   1020			= fiji_fan_table->ucFanControlMode;
   1021		hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanPWM
   1022			= le16_to_cpu(fiji_fan_table->usFanPWMMax);
   1023		hwmgr->thermal_controller.advanceFanControlParameters.usDefaultFanOutputSensitivity
   1024			= 4836;
   1025		hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity
   1026			= le16_to_cpu(fiji_fan_table->usFanOutputSensitivity);
   1027		hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanRPM
   1028			= le16_to_cpu(fiji_fan_table->usFanRPMMax);
   1029		hwmgr->thermal_controller.advanceFanControlParameters.ulMinFanSCLKAcousticLimit
   1030			= (le32_to_cpu(fiji_fan_table->ulMinFanSCLKAcousticLimit) / 100); /* PPTable stores it in 10Khz unit for 2 decimal places.  SMC wants MHz. */
   1031		hwmgr->thermal_controller.advanceFanControlParameters.ucTargetTemperature
   1032			= fiji_fan_table->ucTargetTemperature;
   1033		hwmgr->thermal_controller.advanceFanControlParameters.ucMinimumPWMLimit
   1034			= fiji_fan_table->ucMinimumPWMLimit;
   1035
   1036		hwmgr->thermal_controller.advanceFanControlParameters.usFanGainEdge
   1037			= le16_to_cpu(fiji_fan_table->usFanGainEdge);
   1038		hwmgr->thermal_controller.advanceFanControlParameters.usFanGainHotspot
   1039			= le16_to_cpu(fiji_fan_table->usFanGainHotspot);
   1040		hwmgr->thermal_controller.advanceFanControlParameters.usFanGainLiquid
   1041			= le16_to_cpu(fiji_fan_table->usFanGainLiquid);
   1042		hwmgr->thermal_controller.advanceFanControlParameters.usFanGainVrVddc
   1043			= le16_to_cpu(fiji_fan_table->usFanGainVrVddc);
   1044		hwmgr->thermal_controller.advanceFanControlParameters.usFanGainVrMvdd
   1045			= le16_to_cpu(fiji_fan_table->usFanGainVrMvdd);
   1046		hwmgr->thermal_controller.advanceFanControlParameters.usFanGainPlx
   1047			= le16_to_cpu(fiji_fan_table->usFanGainPlx);
   1048		hwmgr->thermal_controller.advanceFanControlParameters.usFanGainHbm
   1049			= le16_to_cpu(fiji_fan_table->usFanGainHbm);
   1050	} else if (fan_table->ucRevId >= 9) {
   1051		const ATOM_Polaris_Fan_Table *polaris_fan_table =
   1052			(ATOM_Polaris_Fan_Table *)fan_table;
   1053		hwmgr->thermal_controller.advanceFanControlParameters.ucTHyst
   1054			= polaris_fan_table->ucTHyst;
   1055		hwmgr->thermal_controller.advanceFanControlParameters.usTMin
   1056			= le16_to_cpu(polaris_fan_table->usTMin);
   1057		hwmgr->thermal_controller.advanceFanControlParameters.usTMed
   1058			= le16_to_cpu(polaris_fan_table->usTMed);
   1059		hwmgr->thermal_controller.advanceFanControlParameters.usTHigh
   1060			= le16_to_cpu(polaris_fan_table->usTHigh);
   1061		hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin
   1062			= le16_to_cpu(polaris_fan_table->usPWMMin);
   1063		hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed
   1064			= le16_to_cpu(polaris_fan_table->usPWMMed);
   1065		hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh
   1066			= le16_to_cpu(polaris_fan_table->usPWMHigh);
   1067		hwmgr->thermal_controller.advanceFanControlParameters.usTMax
   1068			= le16_to_cpu(polaris_fan_table->usTMax);
   1069		hwmgr->thermal_controller.advanceFanControlParameters.ucFanControlMode
   1070			= polaris_fan_table->ucFanControlMode;
   1071		hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanPWM
   1072			= le16_to_cpu(polaris_fan_table->usFanPWMMax);
   1073		hwmgr->thermal_controller.advanceFanControlParameters.usDefaultFanOutputSensitivity
   1074			= 4836;
   1075		hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity
   1076			= le16_to_cpu(polaris_fan_table->usFanOutputSensitivity);
   1077		hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanRPM
   1078			= le16_to_cpu(polaris_fan_table->usFanRPMMax);
   1079		hwmgr->thermal_controller.advanceFanControlParameters.ulMinFanSCLKAcousticLimit
   1080			= (le32_to_cpu(polaris_fan_table->ulMinFanSCLKAcousticLimit) / 100); /* PPTable stores it in 10Khz unit for 2 decimal places.  SMC wants MHz. */
   1081		hwmgr->thermal_controller.advanceFanControlParameters.ucTargetTemperature
   1082			= polaris_fan_table->ucTargetTemperature;
   1083		hwmgr->thermal_controller.advanceFanControlParameters.ucMinimumPWMLimit
   1084			= polaris_fan_table->ucMinimumPWMLimit;
   1085
   1086		hwmgr->thermal_controller.advanceFanControlParameters.usFanGainEdge
   1087			= le16_to_cpu(polaris_fan_table->usFanGainEdge);
   1088		hwmgr->thermal_controller.advanceFanControlParameters.usFanGainHotspot
   1089			= le16_to_cpu(polaris_fan_table->usFanGainHotspot);
   1090		hwmgr->thermal_controller.advanceFanControlParameters.usFanGainLiquid
   1091			= le16_to_cpu(polaris_fan_table->usFanGainLiquid);
   1092		hwmgr->thermal_controller.advanceFanControlParameters.usFanGainVrVddc
   1093			= le16_to_cpu(polaris_fan_table->usFanGainVrVddc);
   1094		hwmgr->thermal_controller.advanceFanControlParameters.usFanGainVrMvdd
   1095			= le16_to_cpu(polaris_fan_table->usFanGainVrMvdd);
   1096		hwmgr->thermal_controller.advanceFanControlParameters.usFanGainPlx
   1097			= le16_to_cpu(polaris_fan_table->usFanGainPlx);
   1098		hwmgr->thermal_controller.advanceFanControlParameters.usFanGainHbm
   1099			= le16_to_cpu(polaris_fan_table->usFanGainHbm);
   1100		hwmgr->thermal_controller.advanceFanControlParameters.ucEnableZeroRPM
   1101			= le16_to_cpu(polaris_fan_table->ucEnableZeroRPM);
   1102		hwmgr->thermal_controller.advanceFanControlParameters.ucFanStopTemperature
   1103			= le16_to_cpu(polaris_fan_table->ucFanStopTemperature);
   1104		hwmgr->thermal_controller.advanceFanControlParameters.ucFanStartTemperature
   1105			= le16_to_cpu(polaris_fan_table->ucFanStartTemperature);
   1106	}
   1107
   1108	return 0;
   1109}
   1110
   1111/**
   1112 * check_powerplay_tables - Private Function used during initialization.
   1113 * Inspect the PowerPlay table for obvious signs of corruption.
   1114 * @hwmgr: Pointer to the hardware manager.
   1115 * @powerplay_table: Pointer to the PowerPlay Table.
   1116 * Exception:  2 if the powerplay table is incorrect.
   1117 */
   1118static int check_powerplay_tables(
   1119		struct pp_hwmgr *hwmgr,
   1120		const ATOM_Tonga_POWERPLAYTABLE *powerplay_table
   1121		)
   1122{
   1123	const ATOM_Tonga_State_Array *state_arrays;
   1124
   1125	state_arrays = (ATOM_Tonga_State_Array *)(((unsigned long)powerplay_table) +
   1126		le16_to_cpu(powerplay_table->usStateArrayOffset));
   1127
   1128	PP_ASSERT_WITH_CODE((ATOM_Tonga_TABLE_REVISION_TONGA <=
   1129		powerplay_table->sHeader.ucTableFormatRevision),
   1130		"Unsupported PPTable format!", return -1);
   1131	PP_ASSERT_WITH_CODE((0 != powerplay_table->usStateArrayOffset),
   1132		"State table is not set!", return -1);
   1133	PP_ASSERT_WITH_CODE((0 < powerplay_table->sHeader.usStructureSize),
   1134		"Invalid PowerPlay Table!", return -1);
   1135	PP_ASSERT_WITH_CODE((0 < state_arrays->ucNumEntries),
   1136		"Invalid PowerPlay Table!", return -1);
   1137
   1138	return 0;
   1139}
   1140
   1141static int pp_tables_v1_0_initialize(struct pp_hwmgr *hwmgr)
   1142{
   1143	int result = 0;
   1144	const ATOM_Tonga_POWERPLAYTABLE *powerplay_table;
   1145
   1146	hwmgr->pptable = kzalloc(sizeof(struct phm_ppt_v1_information), GFP_KERNEL);
   1147
   1148	PP_ASSERT_WITH_CODE((NULL != hwmgr->pptable),
   1149			    "Failed to allocate hwmgr->pptable!", return -ENOMEM);
   1150
   1151	powerplay_table = get_powerplay_table(hwmgr);
   1152
   1153	PP_ASSERT_WITH_CODE((NULL != powerplay_table),
   1154		"Missing PowerPlay Table!", return -1);
   1155
   1156	result = check_powerplay_tables(hwmgr, powerplay_table);
   1157
   1158	PP_ASSERT_WITH_CODE((result == 0),
   1159			    "check_powerplay_tables failed", return result);
   1160
   1161	result = set_platform_caps(hwmgr,
   1162				   le32_to_cpu(powerplay_table->ulPlatformCaps));
   1163
   1164	PP_ASSERT_WITH_CODE((result == 0),
   1165			    "set_platform_caps failed", return result);
   1166
   1167	result = init_thermal_controller(hwmgr, powerplay_table);
   1168
   1169	PP_ASSERT_WITH_CODE((result == 0),
   1170			    "init_thermal_controller failed", return result);
   1171
   1172	result = init_over_drive_limits(hwmgr, powerplay_table);
   1173
   1174	PP_ASSERT_WITH_CODE((result == 0),
   1175			    "init_over_drive_limits failed", return result);
   1176
   1177	result = init_clock_voltage_dependency(hwmgr, powerplay_table);
   1178
   1179	PP_ASSERT_WITH_CODE((result == 0),
   1180			    "init_clock_voltage_dependency failed", return result);
   1181
   1182	result = init_dpm_2_parameters(hwmgr, powerplay_table);
   1183
   1184	PP_ASSERT_WITH_CODE((result == 0),
   1185			    "init_dpm_2_parameters failed", return result);
   1186
   1187	return result;
   1188}
   1189
   1190static int pp_tables_v1_0_uninitialize(struct pp_hwmgr *hwmgr)
   1191{
   1192	struct phm_ppt_v1_information *pp_table_information =
   1193		(struct phm_ppt_v1_information *)(hwmgr->pptable);
   1194
   1195	kfree(pp_table_information->vdd_dep_on_sclk);
   1196	pp_table_information->vdd_dep_on_sclk = NULL;
   1197
   1198	kfree(pp_table_information->vdd_dep_on_mclk);
   1199	pp_table_information->vdd_dep_on_mclk = NULL;
   1200
   1201	kfree(pp_table_information->valid_mclk_values);
   1202	pp_table_information->valid_mclk_values = NULL;
   1203
   1204	kfree(pp_table_information->valid_sclk_values);
   1205	pp_table_information->valid_sclk_values = NULL;
   1206
   1207	kfree(pp_table_information->vddc_lookup_table);
   1208	pp_table_information->vddc_lookup_table = NULL;
   1209
   1210	kfree(pp_table_information->vddgfx_lookup_table);
   1211	pp_table_information->vddgfx_lookup_table = NULL;
   1212
   1213	kfree(pp_table_information->mm_dep_table);
   1214	pp_table_information->mm_dep_table = NULL;
   1215
   1216	kfree(pp_table_information->cac_dtp_table);
   1217	pp_table_information->cac_dtp_table = NULL;
   1218
   1219	kfree(hwmgr->dyn_state.cac_dtp_table);
   1220	hwmgr->dyn_state.cac_dtp_table = NULL;
   1221
   1222	kfree(pp_table_information->ppm_parameter_table);
   1223	pp_table_information->ppm_parameter_table = NULL;
   1224
   1225	kfree(pp_table_information->pcie_table);
   1226	pp_table_information->pcie_table = NULL;
   1227
   1228	kfree(pp_table_information->gpio_table);
   1229	pp_table_information->gpio_table = NULL;
   1230
   1231	kfree(hwmgr->pptable);
   1232	hwmgr->pptable = NULL;
   1233
   1234	return 0;
   1235}
   1236
   1237const struct pp_table_func pptable_v1_0_funcs = {
   1238	.pptable_init = pp_tables_v1_0_initialize,
   1239	.pptable_fini = pp_tables_v1_0_uninitialize,
   1240};
   1241
   1242int get_number_of_powerplay_table_entries_v1_0(struct pp_hwmgr *hwmgr)
   1243{
   1244	ATOM_Tonga_State_Array const *state_arrays;
   1245	const ATOM_Tonga_POWERPLAYTABLE *pp_table = get_powerplay_table(hwmgr);
   1246
   1247	PP_ASSERT_WITH_CODE((NULL != pp_table),
   1248			"Missing PowerPlay Table!", return -1);
   1249	PP_ASSERT_WITH_CODE((pp_table->sHeader.ucTableFormatRevision >=
   1250			ATOM_Tonga_TABLE_REVISION_TONGA),
   1251			"Incorrect PowerPlay table revision!", return -1);
   1252
   1253	state_arrays = (ATOM_Tonga_State_Array *)(((unsigned long)pp_table) +
   1254			le16_to_cpu(pp_table->usStateArrayOffset));
   1255
   1256	return (uint32_t)(state_arrays->ucNumEntries);
   1257}
   1258
   1259/*
   1260 * Private function to convert flags stored in the BIOS to software flags in PowerPlay.
   1261 */
   1262static uint32_t make_classification_flags(struct pp_hwmgr *hwmgr,
   1263		uint16_t classification, uint16_t classification2)
   1264{
   1265	uint32_t result = 0;
   1266
   1267	if (classification & ATOM_PPLIB_CLASSIFICATION_BOOT)
   1268		result |= PP_StateClassificationFlag_Boot;
   1269
   1270	if (classification & ATOM_PPLIB_CLASSIFICATION_THERMAL)
   1271		result |= PP_StateClassificationFlag_Thermal;
   1272
   1273	if (classification & ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE)
   1274		result |= PP_StateClassificationFlag_LimitedPowerSource;
   1275
   1276	if (classification & ATOM_PPLIB_CLASSIFICATION_REST)
   1277		result |= PP_StateClassificationFlag_Rest;
   1278
   1279	if (classification & ATOM_PPLIB_CLASSIFICATION_FORCED)
   1280		result |= PP_StateClassificationFlag_Forced;
   1281
   1282	if (classification & ATOM_PPLIB_CLASSIFICATION_ACPI)
   1283		result |= PP_StateClassificationFlag_ACPI;
   1284
   1285	if (classification2 & ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2)
   1286		result |= PP_StateClassificationFlag_LimitedPowerSource_2;
   1287
   1288	return result;
   1289}
   1290
   1291static int ppt_get_num_of_vce_state_table_entries_v1_0(struct pp_hwmgr *hwmgr)
   1292{
   1293	const ATOM_Tonga_POWERPLAYTABLE *pp_table = get_powerplay_table(hwmgr);
   1294	const ATOM_Tonga_VCE_State_Table *vce_state_table;
   1295
   1296
   1297	if (pp_table == NULL)
   1298		return 0;
   1299
   1300	vce_state_table = (void *)pp_table +
   1301			le16_to_cpu(pp_table->usVCEStateTableOffset);
   1302
   1303	return vce_state_table->ucNumEntries;
   1304}
   1305
   1306static int ppt_get_vce_state_table_entry_v1_0(struct pp_hwmgr *hwmgr, uint32_t i,
   1307		struct amd_vce_state *vce_state, void **clock_info, uint32_t *flag)
   1308{
   1309	const ATOM_Tonga_VCE_State_Record *vce_state_record;
   1310	ATOM_Tonga_SCLK_Dependency_Record *sclk_dep_record;
   1311	ATOM_Tonga_MCLK_Dependency_Record *mclk_dep_record;
   1312	ATOM_Tonga_MM_Dependency_Record *mm_dep_record;
   1313	const ATOM_Tonga_POWERPLAYTABLE *pptable = get_powerplay_table(hwmgr);
   1314	const ATOM_Tonga_VCE_State_Table *vce_state_table = (ATOM_Tonga_VCE_State_Table *)(((unsigned long)pptable)
   1315							  + le16_to_cpu(pptable->usVCEStateTableOffset));
   1316	const ATOM_Tonga_SCLK_Dependency_Table *sclk_dep_table = (ATOM_Tonga_SCLK_Dependency_Table *)(((unsigned long)pptable)
   1317							  + le16_to_cpu(pptable->usSclkDependencyTableOffset));
   1318	const ATOM_Tonga_MCLK_Dependency_Table *mclk_dep_table = (ATOM_Tonga_MCLK_Dependency_Table *)(((unsigned long)pptable)
   1319							  + le16_to_cpu(pptable->usMclkDependencyTableOffset));
   1320	const ATOM_Tonga_MM_Dependency_Table *mm_dep_table = (ATOM_Tonga_MM_Dependency_Table *)(((unsigned long)pptable)
   1321							  + le16_to_cpu(pptable->usMMDependencyTableOffset));
   1322
   1323	PP_ASSERT_WITH_CODE((i < vce_state_table->ucNumEntries),
   1324			 "Requested state entry ID is out of range!",
   1325			 return -EINVAL);
   1326
   1327	vce_state_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
   1328					ATOM_Tonga_VCE_State_Record,
   1329					entries, vce_state_table, i);
   1330	sclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
   1331					ATOM_Tonga_SCLK_Dependency_Record,
   1332					entries, sclk_dep_table,
   1333					vce_state_record->ucSCLKIndex);
   1334	mm_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
   1335					ATOM_Tonga_MM_Dependency_Record,
   1336					entries, mm_dep_table,
   1337					vce_state_record->ucVCEClockIndex);
   1338	*flag = vce_state_record->ucFlag;
   1339
   1340	vce_state->evclk = le32_to_cpu(mm_dep_record->ulEClk);
   1341	vce_state->ecclk = le32_to_cpu(mm_dep_record->ulEClk);
   1342	vce_state->sclk = le32_to_cpu(sclk_dep_record->ulSclk);
   1343
   1344	if (vce_state_record->ucMCLKIndex >= mclk_dep_table->ucNumEntries)
   1345		mclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
   1346					ATOM_Tonga_MCLK_Dependency_Record,
   1347					entries, mclk_dep_table,
   1348					mclk_dep_table->ucNumEntries - 1);
   1349	else
   1350		mclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
   1351					ATOM_Tonga_MCLK_Dependency_Record,
   1352					entries, mclk_dep_table,
   1353					vce_state_record->ucMCLKIndex);
   1354
   1355	vce_state->mclk = le32_to_cpu(mclk_dep_record->ulMclk);
   1356	return 0;
   1357}
   1358
   1359/**
   1360 * get_powerplay_table_entry_v1_0 - Create a Power State out of an entry in the PowerPlay table.
   1361 * This function is called by the hardware back-end.
   1362 * @hwmgr: Pointer to the hardware manager.
   1363 * @entry_index: The index of the entry to be extracted from the table.
   1364 * @power_state: The address of the PowerState instance being created.
   1365 * @call_back_func: The function to call into to fill power state
   1366 * Return: -1 if the entry cannot be retrieved.
   1367 */
   1368int get_powerplay_table_entry_v1_0(struct pp_hwmgr *hwmgr,
   1369		uint32_t entry_index, struct pp_power_state *power_state,
   1370		int (*call_back_func)(struct pp_hwmgr *, void *,
   1371				struct pp_power_state *, void *, uint32_t))
   1372{
   1373	int result = 0;
   1374	const ATOM_Tonga_State_Array *state_arrays;
   1375	const ATOM_Tonga_State *state_entry;
   1376	const ATOM_Tonga_POWERPLAYTABLE *pp_table = get_powerplay_table(hwmgr);
   1377	int i, j;
   1378	uint32_t flags = 0;
   1379
   1380	PP_ASSERT_WITH_CODE((NULL != pp_table), "Missing PowerPlay Table!", return -1;);
   1381	power_state->classification.bios_index = entry_index;
   1382
   1383	if (pp_table->sHeader.ucTableFormatRevision >=
   1384			ATOM_Tonga_TABLE_REVISION_TONGA) {
   1385		state_arrays = (ATOM_Tonga_State_Array *)(((unsigned long)pp_table) +
   1386				le16_to_cpu(pp_table->usStateArrayOffset));
   1387
   1388		PP_ASSERT_WITH_CODE((0 < pp_table->usStateArrayOffset),
   1389				"Invalid PowerPlay Table State Array Offset.", return -1);
   1390		PP_ASSERT_WITH_CODE((0 < state_arrays->ucNumEntries),
   1391				"Invalid PowerPlay Table State Array.", return -1);
   1392		PP_ASSERT_WITH_CODE((entry_index <= state_arrays->ucNumEntries),
   1393				"Invalid PowerPlay Table State Array Entry.", return -1);
   1394
   1395		state_entry = GET_FLEXIBLE_ARRAY_MEMBER_ADDR(
   1396						ATOM_Tonga_State, entries,
   1397						state_arrays, entry_index);
   1398
   1399		result = call_back_func(hwmgr, (void *)state_entry, power_state,
   1400				(void *)pp_table,
   1401				make_classification_flags(hwmgr,
   1402					le16_to_cpu(state_entry->usClassification),
   1403					le16_to_cpu(state_entry->usClassification2)));
   1404	}
   1405
   1406	if (!result && (power_state->classification.flags &
   1407			PP_StateClassificationFlag_Boot))
   1408		result = hwmgr->hwmgr_func->patch_boot_state(hwmgr, &(power_state->hardware));
   1409
   1410	hwmgr->num_vce_state_tables = i = ppt_get_num_of_vce_state_table_entries_v1_0(hwmgr);
   1411
   1412	if ((i != 0) && (i <= AMD_MAX_VCE_LEVELS)) {
   1413		for (j = 0; j < i; j++)
   1414			ppt_get_vce_state_table_entry_v1_0(hwmgr, j, &(hwmgr->vce_states[j]), NULL, &flags);
   1415	}
   1416
   1417	return result;
   1418}
   1419