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

vega12_processpptables.c (14944B)


      1/*
      2 * Copyright 2017 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 <linux/module.h>
     24#include <linux/slab.h>
     25#include <linux/fb.h>
     26
     27#include "vega12/smu9_driver_if.h"
     28#include "vega12_processpptables.h"
     29#include "ppatomfwctrl.h"
     30#include "atomfirmware.h"
     31#include "pp_debug.h"
     32#include "cgs_common.h"
     33#include "vega12_pptable.h"
     34
     35static void set_hw_cap(struct pp_hwmgr *hwmgr, bool enable,
     36		enum phm_platform_caps cap)
     37{
     38	if (enable)
     39		phm_cap_set(hwmgr->platform_descriptor.platformCaps, cap);
     40	else
     41		phm_cap_unset(hwmgr->platform_descriptor.platformCaps, cap);
     42}
     43
     44static const void *get_powerplay_table(struct pp_hwmgr *hwmgr)
     45{
     46	int index = GetIndexIntoMasterDataTable(powerplayinfo);
     47
     48	u16 size;
     49	u8 frev, crev;
     50	const void *table_address = hwmgr->soft_pp_table;
     51
     52	if (!table_address) {
     53		table_address = (ATOM_Vega12_POWERPLAYTABLE *)
     54				smu_atom_get_data_table(hwmgr->adev, index,
     55						&size, &frev, &crev);
     56
     57		hwmgr->soft_pp_table = table_address;	/*Cache the result in RAM.*/
     58		hwmgr->soft_pp_table_size = size;
     59	}
     60
     61	return table_address;
     62}
     63
     64static int check_powerplay_tables(
     65		struct pp_hwmgr *hwmgr,
     66		const ATOM_Vega12_POWERPLAYTABLE *powerplay_table)
     67{
     68	PP_ASSERT_WITH_CODE((powerplay_table->sHeader.format_revision >=
     69		ATOM_VEGA12_TABLE_REVISION_VEGA12),
     70		"Unsupported PPTable format!", return -1);
     71	PP_ASSERT_WITH_CODE(powerplay_table->sHeader.structuresize > 0,
     72		"Invalid PowerPlay Table!", return -1);
     73
     74	return 0;
     75}
     76
     77static int set_platform_caps(struct pp_hwmgr *hwmgr, uint32_t powerplay_caps)
     78{
     79	set_hw_cap(
     80			hwmgr,
     81			0 != (powerplay_caps & ATOM_VEGA12_PP_PLATFORM_CAP_POWERPLAY),
     82			PHM_PlatformCaps_PowerPlaySupport);
     83
     84	set_hw_cap(
     85			hwmgr,
     86			0 != (powerplay_caps & ATOM_VEGA12_PP_PLATFORM_CAP_SBIOSPOWERSOURCE),
     87			PHM_PlatformCaps_BiosPowerSourceControl);
     88
     89	set_hw_cap(
     90			hwmgr,
     91			0 != (powerplay_caps & ATOM_VEGA12_PP_PLATFORM_CAP_BACO),
     92			PHM_PlatformCaps_BACO);
     93
     94	set_hw_cap(
     95			hwmgr,
     96			0 != (powerplay_caps & ATOM_VEGA12_PP_PLATFORM_CAP_BAMACO),
     97			 PHM_PlatformCaps_BAMACO);
     98
     99	return 0;
    100}
    101
    102static int append_vbios_pptable(struct pp_hwmgr *hwmgr, PPTable_t *ppsmc_pptable)
    103{
    104	struct pp_atomfwctrl_smc_dpm_parameters smc_dpm_table;
    105
    106	PP_ASSERT_WITH_CODE(
    107		pp_atomfwctrl_get_smc_dpm_information(hwmgr, &smc_dpm_table) == 0,
    108		"[appendVbiosPPTable] Failed to retrieve Smc Dpm Table from VBIOS!",
    109		return -1);
    110
    111	ppsmc_pptable->Liquid1_I2C_address = smc_dpm_table.liquid1_i2c_address;
    112	ppsmc_pptable->Liquid2_I2C_address = smc_dpm_table.liquid2_i2c_address;
    113	ppsmc_pptable->Vr_I2C_address = smc_dpm_table.vr_i2c_address;
    114	ppsmc_pptable->Plx_I2C_address = smc_dpm_table.plx_i2c_address;
    115
    116	ppsmc_pptable->Liquid_I2C_LineSCL = smc_dpm_table.liquid_i2c_linescl;
    117	ppsmc_pptable->Liquid_I2C_LineSDA = smc_dpm_table.liquid_i2c_linesda;
    118	ppsmc_pptable->Vr_I2C_LineSCL = smc_dpm_table.vr_i2c_linescl;
    119	ppsmc_pptable->Vr_I2C_LineSDA = smc_dpm_table.vr_i2c_linesda;
    120
    121	ppsmc_pptable->Plx_I2C_LineSCL = smc_dpm_table.plx_i2c_linescl;
    122	ppsmc_pptable->Plx_I2C_LineSDA = smc_dpm_table.plx_i2c_linesda;
    123	ppsmc_pptable->VrSensorPresent = smc_dpm_table.vrsensorpresent;
    124	ppsmc_pptable->LiquidSensorPresent = smc_dpm_table.liquidsensorpresent;
    125
    126	ppsmc_pptable->MaxVoltageStepGfx = smc_dpm_table.maxvoltagestepgfx;
    127	ppsmc_pptable->MaxVoltageStepSoc = smc_dpm_table.maxvoltagestepsoc;
    128
    129	ppsmc_pptable->VddGfxVrMapping = smc_dpm_table.vddgfxvrmapping;
    130	ppsmc_pptable->VddSocVrMapping = smc_dpm_table.vddsocvrmapping;
    131	ppsmc_pptable->VddMem0VrMapping = smc_dpm_table.vddmem0vrmapping;
    132	ppsmc_pptable->VddMem1VrMapping = smc_dpm_table.vddmem1vrmapping;
    133
    134	ppsmc_pptable->GfxUlvPhaseSheddingMask = smc_dpm_table.gfxulvphasesheddingmask;
    135	ppsmc_pptable->SocUlvPhaseSheddingMask = smc_dpm_table.soculvphasesheddingmask;
    136
    137	ppsmc_pptable->GfxMaxCurrent = smc_dpm_table.gfxmaxcurrent;
    138	ppsmc_pptable->GfxOffset = smc_dpm_table.gfxoffset;
    139	ppsmc_pptable->Padding_TelemetryGfx = smc_dpm_table.padding_telemetrygfx;
    140
    141	ppsmc_pptable->SocMaxCurrent = smc_dpm_table.socmaxcurrent;
    142	ppsmc_pptable->SocOffset = smc_dpm_table.socoffset;
    143	ppsmc_pptable->Padding_TelemetrySoc = smc_dpm_table.padding_telemetrysoc;
    144
    145	ppsmc_pptable->Mem0MaxCurrent = smc_dpm_table.mem0maxcurrent;
    146	ppsmc_pptable->Mem0Offset = smc_dpm_table.mem0offset;
    147	ppsmc_pptable->Padding_TelemetryMem0 = smc_dpm_table.padding_telemetrymem0;
    148
    149	ppsmc_pptable->Mem1MaxCurrent = smc_dpm_table.mem1maxcurrent;
    150	ppsmc_pptable->Mem1Offset = smc_dpm_table.mem1offset;
    151	ppsmc_pptable->Padding_TelemetryMem1 = smc_dpm_table.padding_telemetrymem1;
    152
    153	ppsmc_pptable->AcDcGpio = smc_dpm_table.acdcgpio;
    154	ppsmc_pptable->AcDcPolarity = smc_dpm_table.acdcpolarity;
    155	ppsmc_pptable->VR0HotGpio = smc_dpm_table.vr0hotgpio;
    156	ppsmc_pptable->VR0HotPolarity = smc_dpm_table.vr0hotpolarity;
    157
    158	ppsmc_pptable->VR1HotGpio = smc_dpm_table.vr1hotgpio;
    159	ppsmc_pptable->VR1HotPolarity = smc_dpm_table.vr1hotpolarity;
    160	ppsmc_pptable->Padding1 = smc_dpm_table.padding1;
    161	ppsmc_pptable->Padding2 = smc_dpm_table.padding2;
    162
    163	ppsmc_pptable->LedPin0 = smc_dpm_table.ledpin0;
    164	ppsmc_pptable->LedPin1 = smc_dpm_table.ledpin1;
    165	ppsmc_pptable->LedPin2 = smc_dpm_table.ledpin2;
    166
    167	ppsmc_pptable->PllGfxclkSpreadEnabled = smc_dpm_table.pllgfxclkspreadenabled;
    168	ppsmc_pptable->PllGfxclkSpreadPercent = smc_dpm_table.pllgfxclkspreadpercent;
    169	ppsmc_pptable->PllGfxclkSpreadFreq = smc_dpm_table.pllgfxclkspreadfreq;
    170
    171	ppsmc_pptable->UclkSpreadEnabled = 0;
    172	ppsmc_pptable->UclkSpreadPercent = smc_dpm_table.uclkspreadpercent;
    173	ppsmc_pptable->UclkSpreadFreq = smc_dpm_table.uclkspreadfreq;
    174
    175	ppsmc_pptable->SocclkSpreadEnabled = 0;
    176	ppsmc_pptable->SocclkSpreadPercent = smc_dpm_table.socclkspreadpercent;
    177	ppsmc_pptable->SocclkSpreadFreq = smc_dpm_table.socclkspreadfreq;
    178
    179	ppsmc_pptable->AcgGfxclkSpreadEnabled = smc_dpm_table.acggfxclkspreadenabled;
    180	ppsmc_pptable->AcgGfxclkSpreadPercent = smc_dpm_table.acggfxclkspreadpercent;
    181	ppsmc_pptable->AcgGfxclkSpreadFreq = smc_dpm_table.acggfxclkspreadfreq;
    182
    183	ppsmc_pptable->Vr2_I2C_address = smc_dpm_table.Vr2_I2C_address;
    184
    185	ppsmc_pptable->Vr2_I2C_address = smc_dpm_table.Vr2_I2C_address;
    186
    187	return 0;
    188}
    189
    190#define VEGA12_ENGINECLOCK_HARDMAX 198000
    191static int init_powerplay_table_information(
    192		struct pp_hwmgr *hwmgr,
    193		const ATOM_Vega12_POWERPLAYTABLE *powerplay_table)
    194{
    195	struct phm_ppt_v3_information *pptable_information =
    196		(struct phm_ppt_v3_information *)hwmgr->pptable;
    197	uint32_t disable_power_control = 0;
    198	int result;
    199
    200	hwmgr->thermal_controller.ucType = powerplay_table->ucThermalControllerType;
    201	pptable_information->uc_thermal_controller_type = powerplay_table->ucThermalControllerType;
    202
    203	set_hw_cap(hwmgr,
    204		ATOM_VEGA12_PP_THERMALCONTROLLER_NONE != hwmgr->thermal_controller.ucType,
    205		PHM_PlatformCaps_ThermalController);
    206
    207	phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl);
    208
    209	if (le32_to_cpu(powerplay_table->ODSettingsMax[ATOM_VEGA12_ODSETTING_GFXCLKFMAX]) > VEGA12_ENGINECLOCK_HARDMAX)
    210		hwmgr->platform_descriptor.overdriveLimit.engineClock = VEGA12_ENGINECLOCK_HARDMAX;
    211	else
    212		hwmgr->platform_descriptor.overdriveLimit.engineClock =
    213			le32_to_cpu(powerplay_table->ODSettingsMax[ATOM_VEGA12_ODSETTING_GFXCLKFMAX]);
    214	hwmgr->platform_descriptor.overdriveLimit.memoryClock =
    215		le32_to_cpu(powerplay_table->ODSettingsMax[ATOM_VEGA12_ODSETTING_UCLKFMAX]);
    216
    217	phm_copy_overdrive_settings_limits_array(hwmgr,
    218						 &pptable_information->od_settings_max,
    219						 powerplay_table->ODSettingsMax,
    220						 ATOM_VEGA12_ODSETTING_COUNT);
    221	phm_copy_overdrive_settings_limits_array(hwmgr,
    222						 &pptable_information->od_settings_min,
    223						 powerplay_table->ODSettingsMin,
    224						 ATOM_VEGA12_ODSETTING_COUNT);
    225
    226	/* hwmgr->platformDescriptor.minOverdriveVDDC = 0;
    227	hwmgr->platformDescriptor.maxOverdriveVDDC = 0;
    228	hwmgr->platformDescriptor.overdriveVDDCStep = 0; */
    229
    230	if (hwmgr->platform_descriptor.overdriveLimit.engineClock > 0
    231		&& hwmgr->platform_descriptor.overdriveLimit.memoryClock > 0)
    232		phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_ACOverdriveSupport);
    233
    234	pptable_information->us_small_power_limit1 = le16_to_cpu(powerplay_table->usSmallPowerLimit1);
    235	pptable_information->us_small_power_limit2 = le16_to_cpu(powerplay_table->usSmallPowerLimit2);
    236	pptable_information->us_boost_power_limit = le16_to_cpu(powerplay_table->usBoostPowerLimit);
    237	pptable_information->us_od_turbo_power_limit = le16_to_cpu(powerplay_table->usODTurboPowerLimit);
    238	pptable_information->us_od_powersave_power_limit = le16_to_cpu(powerplay_table->usODPowerSavePowerLimit);
    239
    240	pptable_information->us_software_shutdown_temp = le16_to_cpu(powerplay_table->usSoftwareShutdownTemp);
    241
    242	hwmgr->platform_descriptor.TDPODLimit = le32_to_cpu(powerplay_table->ODSettingsMax[ATOM_VEGA12_ODSETTING_POWERPERCENTAGE]);
    243
    244	disable_power_control = 0;
    245	if (!disable_power_control) {
    246		/* enable TDP overdrive (PowerControl) feature as well if supported */
    247		if (hwmgr->platform_descriptor.TDPODLimit)
    248			phm_cap_set(hwmgr->platform_descriptor.platformCaps,
    249				PHM_PlatformCaps_PowerControl);
    250	}
    251
    252	phm_copy_clock_limits_array(hwmgr, &pptable_information->power_saving_clock_max, powerplay_table->PowerSavingClockMax, ATOM_VEGA12_PPCLOCK_COUNT);
    253	phm_copy_clock_limits_array(hwmgr, &pptable_information->power_saving_clock_min, powerplay_table->PowerSavingClockMin, ATOM_VEGA12_PPCLOCK_COUNT);
    254
    255	pptable_information->smc_pptable = kmemdup(&(powerplay_table->smcPPTable),
    256						   sizeof(PPTable_t), GFP_KERNEL);
    257	if (pptable_information->smc_pptable == NULL)
    258		return -ENOMEM;
    259
    260	result = append_vbios_pptable(hwmgr, (pptable_information->smc_pptable));
    261
    262	return result;
    263}
    264
    265static int vega12_pp_tables_initialize(struct pp_hwmgr *hwmgr)
    266{
    267	int result = 0;
    268	const ATOM_Vega12_POWERPLAYTABLE *powerplay_table;
    269
    270	hwmgr->pptable = kzalloc(sizeof(struct phm_ppt_v3_information), GFP_KERNEL);
    271	PP_ASSERT_WITH_CODE((hwmgr->pptable != NULL),
    272		"Failed to allocate hwmgr->pptable!", return -ENOMEM);
    273
    274	powerplay_table = get_powerplay_table(hwmgr);
    275	PP_ASSERT_WITH_CODE((powerplay_table != NULL),
    276		"Missing PowerPlay Table!", return -1);
    277
    278	result = check_powerplay_tables(hwmgr, powerplay_table);
    279	PP_ASSERT_WITH_CODE((result == 0),
    280		"check_powerplay_tables failed", return result);
    281
    282	result = set_platform_caps(hwmgr,
    283			le32_to_cpu(powerplay_table->ulPlatformCaps));
    284	PP_ASSERT_WITH_CODE((result == 0),
    285		"set_platform_caps failed", return result);
    286
    287	result = init_powerplay_table_information(hwmgr, powerplay_table);
    288	PP_ASSERT_WITH_CODE((result == 0),
    289		"init_powerplay_table_information failed", return result);
    290
    291	return result;
    292}
    293
    294static int vega12_pp_tables_uninitialize(struct pp_hwmgr *hwmgr)
    295{
    296	struct phm_ppt_v3_information *pp_table_info =
    297			(struct phm_ppt_v3_information *)(hwmgr->pptable);
    298
    299	kfree(pp_table_info->power_saving_clock_max);
    300	pp_table_info->power_saving_clock_max = NULL;
    301
    302	kfree(pp_table_info->power_saving_clock_min);
    303	pp_table_info->power_saving_clock_min = NULL;
    304
    305	kfree(pp_table_info->od_settings_max);
    306	pp_table_info->od_settings_max = NULL;
    307
    308	kfree(pp_table_info->od_settings_min);
    309	pp_table_info->od_settings_min = NULL;
    310
    311	kfree(pp_table_info->smc_pptable);
    312	pp_table_info->smc_pptable = NULL;
    313
    314	kfree(hwmgr->pptable);
    315	hwmgr->pptable = NULL;
    316
    317	return 0;
    318}
    319
    320const struct pp_table_func vega12_pptable_funcs = {
    321	.pptable_init = vega12_pp_tables_initialize,
    322	.pptable_fini = vega12_pp_tables_uninitialize,
    323};
    324
    325#if 0
    326static uint32_t make_classification_flags(struct pp_hwmgr *hwmgr,
    327		uint16_t classification, uint16_t classification2)
    328{
    329	uint32_t result = 0;
    330
    331	if (classification & ATOM_PPLIB_CLASSIFICATION_BOOT)
    332		result |= PP_StateClassificationFlag_Boot;
    333
    334	if (classification & ATOM_PPLIB_CLASSIFICATION_THERMAL)
    335		result |= PP_StateClassificationFlag_Thermal;
    336
    337	if (classification & ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE)
    338		result |= PP_StateClassificationFlag_LimitedPowerSource;
    339
    340	if (classification & ATOM_PPLIB_CLASSIFICATION_REST)
    341		result |= PP_StateClassificationFlag_Rest;
    342
    343	if (classification & ATOM_PPLIB_CLASSIFICATION_FORCED)
    344		result |= PP_StateClassificationFlag_Forced;
    345
    346	if (classification & ATOM_PPLIB_CLASSIFICATION_ACPI)
    347		result |= PP_StateClassificationFlag_ACPI;
    348
    349	if (classification2 & ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2)
    350		result |= PP_StateClassificationFlag_LimitedPowerSource_2;
    351
    352	return result;
    353}
    354
    355int vega12_get_powerplay_table_entry(struct pp_hwmgr *hwmgr,
    356		uint32_t entry_index, struct pp_power_state *power_state,
    357		int (*call_back_func)(struct pp_hwmgr *, void *,
    358				struct pp_power_state *, void *, uint32_t))
    359{
    360	int result = 0;
    361	const ATOM_Vega12_State_Array *state_arrays;
    362	const ATOM_Vega12_State *state_entry;
    363	const ATOM_Vega12_POWERPLAYTABLE *pp_table =
    364			get_powerplay_table(hwmgr);
    365
    366	PP_ASSERT_WITH_CODE(pp_table, "Missing PowerPlay Table!",
    367			return -1;);
    368	power_state->classification.bios_index = entry_index;
    369
    370	if (pp_table->sHeader.format_revision >=
    371			ATOM_Vega12_TABLE_REVISION_VEGA12) {
    372		state_arrays = (ATOM_Vega12_State_Array *)
    373				(((unsigned long)pp_table) +
    374				le16_to_cpu(pp_table->usStateArrayOffset));
    375
    376		PP_ASSERT_WITH_CODE(pp_table->usStateArrayOffset > 0,
    377				"Invalid PowerPlay Table State Array Offset.",
    378				return -1);
    379		PP_ASSERT_WITH_CODE(state_arrays->ucNumEntries > 0,
    380				"Invalid PowerPlay Table State Array.",
    381				return -1);
    382		PP_ASSERT_WITH_CODE((entry_index <= state_arrays->ucNumEntries),
    383				"Invalid PowerPlay Table State Array Entry.",
    384				return -1);
    385
    386		state_entry = &(state_arrays->states[entry_index]);
    387
    388		result = call_back_func(hwmgr, (void *)state_entry, power_state,
    389				(void *)pp_table,
    390				make_classification_flags(hwmgr,
    391					le16_to_cpu(state_entry->usClassification),
    392					le16_to_cpu(state_entry->usClassification2)));
    393	}
    394
    395	if (!result && (power_state->classification.flags &
    396			PP_StateClassificationFlag_Boot))
    397		result = hwmgr->hwmgr_func->patch_boot_state(hwmgr, &(power_state->hardware));
    398
    399	return result;
    400}
    401#endif