brintos

brintos / linux-shallow public Read only

0
0
Text · 17.1 KiB · 02ff68b Raw
442 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * AMD Platform Management Framework Driver4 *5 * Copyright (c) 2022, Advanced Micro Devices, Inc.6 * All Rights Reserved.7 *8 * Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>9 */10 11#include <linux/acpi.h>12#include <linux/workqueue.h>13#include "pmf.h"14 15static struct auto_mode_mode_config config_store;16static const char *state_as_str(unsigned int state);17 18#ifdef CONFIG_AMD_PMF_DEBUG19static void amd_pmf_dump_auto_mode_defaults(struct auto_mode_mode_config *data)20{21	struct auto_mode_mode_settings *its_mode;22 23	pr_debug("Auto Mode Data - BEGIN\n");24 25	/* time constant */26	pr_debug("balanced_to_perf: %u ms\n",27		 data->transition[AUTO_TRANSITION_TO_PERFORMANCE].time_constant);28	pr_debug("perf_to_balanced: %u ms\n",29		 data->transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].time_constant);30	pr_debug("quiet_to_balanced: %u ms\n",31		 data->transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].time_constant);32	pr_debug("balanced_to_quiet: %u ms\n",33		 data->transition[AUTO_TRANSITION_TO_QUIET].time_constant);34 35	/* power floor */36	pr_debug("pfloor_perf: %u mW\n", data->mode_set[AUTO_PERFORMANCE].power_floor);37	pr_debug("pfloor_balanced: %u mW\n", data->mode_set[AUTO_BALANCE].power_floor);38	pr_debug("pfloor_quiet: %u mW\n", data->mode_set[AUTO_QUIET].power_floor);39 40	/* Power delta for mode change */41	pr_debug("pd_balanced_to_perf: %u mW\n",42		 data->transition[AUTO_TRANSITION_TO_PERFORMANCE].power_delta);43	pr_debug("pd_perf_to_balanced: %u mW\n",44		 data->transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].power_delta);45	pr_debug("pd_quiet_to_balanced: %u mW\n",46		 data->transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].power_delta);47	pr_debug("pd_balanced_to_quiet: %u mW\n",48		 data->transition[AUTO_TRANSITION_TO_QUIET].power_delta);49 50	/* skin temperature limits */51	its_mode = &data->mode_set[AUTO_PERFORMANCE_ON_LAP];52	pr_debug("stt_apu_perf_on_lap: %u C\n",53		 its_mode->power_control.stt_skin_temp[STT_TEMP_APU]);54	pr_debug("stt_hs2_perf_on_lap: %u C\n",55		 its_mode->power_control.stt_skin_temp[STT_TEMP_HS2]);56	pr_debug("stt_min_limit_perf_on_lap: %u mW\n", its_mode->power_control.stt_min);57 58	its_mode = &data->mode_set[AUTO_PERFORMANCE];59	pr_debug("stt_apu_perf: %u C\n", its_mode->power_control.stt_skin_temp[STT_TEMP_APU]);60	pr_debug("stt_hs2_perf: %u C\n", its_mode->power_control.stt_skin_temp[STT_TEMP_HS2]);61	pr_debug("stt_min_limit_perf: %u mW\n", its_mode->power_control.stt_min);62 63	its_mode = &data->mode_set[AUTO_BALANCE];64	pr_debug("stt_apu_balanced: %u C\n", its_mode->power_control.stt_skin_temp[STT_TEMP_APU]);65	pr_debug("stt_hs2_balanced: %u C\n", its_mode->power_control.stt_skin_temp[STT_TEMP_HS2]);66	pr_debug("stt_min_limit_balanced: %u mW\n", its_mode->power_control.stt_min);67 68	its_mode = &data->mode_set[AUTO_QUIET];69	pr_debug("stt_apu_quiet: %u C\n", its_mode->power_control.stt_skin_temp[STT_TEMP_APU]);70	pr_debug("stt_hs2_quiet: %u C\n", its_mode->power_control.stt_skin_temp[STT_TEMP_HS2]);71	pr_debug("stt_min_limit_quiet: %u mW\n", its_mode->power_control.stt_min);72 73	/* SPL based power limits */74	its_mode = &data->mode_set[AUTO_PERFORMANCE_ON_LAP];75	pr_debug("fppt_perf_on_lap: %u mW\n", its_mode->power_control.fppt);76	pr_debug("sppt_perf_on_lap: %u mW\n", its_mode->power_control.sppt);77	pr_debug("spl_perf_on_lap: %u mW\n", its_mode->power_control.spl);78	pr_debug("sppt_apu_only_perf_on_lap: %u mW\n", its_mode->power_control.sppt_apu_only);79 80	its_mode = &data->mode_set[AUTO_PERFORMANCE];81	pr_debug("fppt_perf: %u mW\n", its_mode->power_control.fppt);82	pr_debug("sppt_perf: %u mW\n", its_mode->power_control.sppt);83	pr_debug("spl_perf: %u mW\n", its_mode->power_control.spl);84	pr_debug("sppt_apu_only_perf: %u mW\n", its_mode->power_control.sppt_apu_only);85 86	its_mode = &data->mode_set[AUTO_BALANCE];87	pr_debug("fppt_balanced: %u mW\n", its_mode->power_control.fppt);88	pr_debug("sppt_balanced: %u mW\n", its_mode->power_control.sppt);89	pr_debug("spl_balanced: %u mW\n", its_mode->power_control.spl);90	pr_debug("sppt_apu_only_balanced: %u mW\n", its_mode->power_control.sppt_apu_only);91 92	its_mode = &data->mode_set[AUTO_QUIET];93	pr_debug("fppt_quiet: %u mW\n", its_mode->power_control.fppt);94	pr_debug("sppt_quiet: %u mW\n", its_mode->power_control.sppt);95	pr_debug("spl_quiet: %u mW\n", its_mode->power_control.spl);96	pr_debug("sppt_apu_only_quiet: %u mW\n", its_mode->power_control.sppt_apu_only);97 98	/* Fan ID */99	pr_debug("fan_id_perf: %lu\n",100		 data->mode_set[AUTO_PERFORMANCE].fan_control.fan_id);101	pr_debug("fan_id_balanced: %lu\n",102		 data->mode_set[AUTO_BALANCE].fan_control.fan_id);103	pr_debug("fan_id_quiet: %lu\n",104		 data->mode_set[AUTO_QUIET].fan_control.fan_id);105 106	pr_debug("Auto Mode Data - END\n");107}108#else109static void amd_pmf_dump_auto_mode_defaults(struct auto_mode_mode_config *data) {}110#endif111 112static void amd_pmf_set_automode(struct amd_pmf_dev *dev, int idx,113				 struct auto_mode_mode_config *table)114{115	struct power_table_control *pwr_ctrl = &config_store.mode_set[idx].power_control;116 117	amd_pmf_send_cmd(dev, SET_SPL, false, pwr_ctrl->spl, NULL);118	amd_pmf_send_cmd(dev, SET_FPPT, false, pwr_ctrl->fppt, NULL);119	amd_pmf_send_cmd(dev, SET_SPPT, false, pwr_ctrl->sppt, NULL);120	amd_pmf_send_cmd(dev, SET_SPPT_APU_ONLY, false, pwr_ctrl->sppt_apu_only, NULL);121	amd_pmf_send_cmd(dev, SET_STT_MIN_LIMIT, false, pwr_ctrl->stt_min, NULL);122	amd_pmf_send_cmd(dev, SET_STT_LIMIT_APU, false,123			 pwr_ctrl->stt_skin_temp[STT_TEMP_APU], NULL);124	amd_pmf_send_cmd(dev, SET_STT_LIMIT_HS2, false,125			 pwr_ctrl->stt_skin_temp[STT_TEMP_HS2], NULL);126 127	if (is_apmf_func_supported(dev, APMF_FUNC_SET_FAN_IDX))128		apmf_update_fan_idx(dev, config_store.mode_set[idx].fan_control.manual,129				    config_store.mode_set[idx].fan_control.fan_id);130}131 132static int amd_pmf_get_moving_avg(struct amd_pmf_dev *pdev, int socket_power)133{134	int i, total = 0;135 136	if (pdev->socket_power_history_idx == -1) {137		for (i = 0; i < AVG_SAMPLE_SIZE; i++)138			pdev->socket_power_history[i] = socket_power;139	}140 141	pdev->socket_power_history_idx = (pdev->socket_power_history_idx + 1) % AVG_SAMPLE_SIZE;142	pdev->socket_power_history[pdev->socket_power_history_idx] = socket_power;143 144	for (i = 0; i < AVG_SAMPLE_SIZE; i++)145		total += pdev->socket_power_history[i];146 147	return total / AVG_SAMPLE_SIZE;148}149 150void amd_pmf_trans_automode(struct amd_pmf_dev *dev, int socket_power, ktime_t time_elapsed_ms)151{152	int avg_power = 0;153	bool update = false;154	int i, j;155 156	/* Get the average moving average computed by auto mode algorithm */157	avg_power = amd_pmf_get_moving_avg(dev, socket_power);158 159	for (i = 0; i < AUTO_TRANSITION_MAX; i++) {160		if ((config_store.transition[i].shifting_up && avg_power >=161		     config_store.transition[i].power_threshold) ||162		    (!config_store.transition[i].shifting_up && avg_power <=163		     config_store.transition[i].power_threshold)) {164			if (config_store.transition[i].timer <165			    config_store.transition[i].time_constant)166				config_store.transition[i].timer += time_elapsed_ms;167		} else {168			config_store.transition[i].timer = 0;169		}170 171		if (config_store.transition[i].timer >=172		    config_store.transition[i].time_constant &&173		    !config_store.transition[i].applied) {174			config_store.transition[i].applied = true;175			update = true;176		} else if (config_store.transition[i].timer <=177			   config_store.transition[i].time_constant &&178			   config_store.transition[i].applied) {179			config_store.transition[i].applied = false;180			update = true;181		}182 183#ifdef CONFIG_AMD_PMF_DEBUG184		dev_dbg(dev->dev, "[AUTO MODE] average_power : %d mW mode: %s\n", avg_power,185			state_as_str(config_store.current_mode));186 187		dev_dbg(dev->dev, "[AUTO MODE] time: %lld ms timer: %u ms tc: %u ms\n",188			time_elapsed_ms, config_store.transition[i].timer,189			config_store.transition[i].time_constant);190 191		dev_dbg(dev->dev, "[AUTO MODE] shiftup: %u pt: %u mW pf: %u mW pd: %u mW\n",192			config_store.transition[i].shifting_up,193			config_store.transition[i].power_threshold,194			config_store.mode_set[i].power_floor,195			config_store.transition[i].power_delta);196#endif197	}198 199	dev_dbg(dev->dev, "[AUTO_MODE] avg power: %u mW mode: %s\n", avg_power,200		state_as_str(config_store.current_mode));201 202#ifdef CONFIG_AMD_PMF_DEBUG203	dev_dbg(dev->dev, "[AUTO MODE] priority1: %u priority2: %u priority3: %u priority4: %u\n",204		config_store.transition[0].applied,205		config_store.transition[1].applied,206		config_store.transition[2].applied,207		config_store.transition[3].applied);208#endif209 210	if (update) {211		for (j = 0; j < AUTO_TRANSITION_MAX; j++) {212			/* Apply the mode with highest priority indentified */213			if (config_store.transition[j].applied) {214				if (config_store.current_mode !=215				    config_store.transition[j].target_mode) {216					config_store.current_mode =217							config_store.transition[j].target_mode;218					dev_dbg(dev->dev, "[AUTO_MODE] moving to mode:%s\n",219						state_as_str(config_store.current_mode));220					amd_pmf_set_automode(dev, config_store.current_mode, NULL);221				}222				break;223			}224		}225	}226}227 228void amd_pmf_update_2_cql(struct amd_pmf_dev *dev, bool is_cql_event)229{230	int mode = config_store.current_mode;231 232	config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].target_mode =233				   is_cql_event ? AUTO_PERFORMANCE_ON_LAP : AUTO_PERFORMANCE;234 235	if ((mode == AUTO_PERFORMANCE || mode == AUTO_PERFORMANCE_ON_LAP) &&236	    mode != config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].target_mode) {237		mode = config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].target_mode;238		amd_pmf_set_automode(dev, mode, NULL);239	}240	dev_dbg(dev->dev, "updated CQL thermals\n");241}242 243static void amd_pmf_get_power_threshold(void)244{245	config_store.transition[AUTO_TRANSITION_TO_QUIET].power_threshold =246				config_store.mode_set[AUTO_BALANCE].power_floor -247				config_store.transition[AUTO_TRANSITION_TO_QUIET].power_delta;248 249	config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].power_threshold =250				config_store.mode_set[AUTO_BALANCE].power_floor -251				config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].power_delta;252 253	config_store.transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].power_threshold =254			config_store.mode_set[AUTO_QUIET].power_floor -255			config_store.transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].power_delta;256 257	config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].power_threshold =258		config_store.mode_set[AUTO_PERFORMANCE].power_floor -259		config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].power_delta;260 261#ifdef CONFIG_AMD_PMF_DEBUG262	pr_debug("[AUTO MODE TO_QUIET] pt: %u mW pf: %u mW pd: %u mW\n",263		 config_store.transition[AUTO_TRANSITION_TO_QUIET].power_threshold,264		 config_store.mode_set[AUTO_BALANCE].power_floor,265		 config_store.transition[AUTO_TRANSITION_TO_QUIET].power_delta);266 267	pr_debug("[AUTO MODE TO_PERFORMANCE] pt: %u mW pf: %u mW pd: %u mW\n",268		 config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].power_threshold,269		 config_store.mode_set[AUTO_BALANCE].power_floor,270		 config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].power_delta);271 272	pr_debug("[AUTO MODE QUIET_TO_BALANCE] pt: %u mW pf: %u mW pd: %u mW\n",273		 config_store.transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE]274		 .power_threshold,275		 config_store.mode_set[AUTO_QUIET].power_floor,276		 config_store.transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].power_delta);277 278	pr_debug("[AUTO MODE PERFORMANCE_TO_BALANCE] pt: %u mW pf: %u mW pd: %u mW\n",279		 config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE]280		 .power_threshold,281		 config_store.mode_set[AUTO_PERFORMANCE].power_floor,282		 config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].power_delta);283#endif284}285 286static const char *state_as_str(unsigned int state)287{288	switch (state) {289	case AUTO_QUIET:290		return "QUIET";291	case AUTO_BALANCE:292		return "BALANCED";293	case AUTO_PERFORMANCE_ON_LAP:294		return "ON_LAP";295	case AUTO_PERFORMANCE:296		return "PERFORMANCE";297	default:298		return "Unknown Auto Mode State";299	}300}301 302static void amd_pmf_load_defaults_auto_mode(struct amd_pmf_dev *dev)303{304	struct apmf_auto_mode output;305	struct power_table_control *pwr_ctrl;306	int i;307 308	apmf_get_auto_mode_def(dev, &output);309	/* time constant */310	config_store.transition[AUTO_TRANSITION_TO_QUIET].time_constant =311								output.balanced_to_quiet;312	config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].time_constant =313								output.balanced_to_perf;314	config_store.transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].time_constant =315								output.quiet_to_balanced;316	config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].time_constant =317								output.perf_to_balanced;318 319	/* power floor */320	config_store.mode_set[AUTO_QUIET].power_floor = output.pfloor_quiet;321	config_store.mode_set[AUTO_BALANCE].power_floor = output.pfloor_balanced;322	config_store.mode_set[AUTO_PERFORMANCE].power_floor = output.pfloor_perf;323	config_store.mode_set[AUTO_PERFORMANCE_ON_LAP].power_floor = output.pfloor_perf;324 325	/* Power delta for mode change */326	config_store.transition[AUTO_TRANSITION_TO_QUIET].power_delta =327								output.pd_balanced_to_quiet;328	config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].power_delta =329								output.pd_balanced_to_perf;330	config_store.transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].power_delta =331								output.pd_quiet_to_balanced;332	config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].power_delta =333								output.pd_perf_to_balanced;334 335	/* Power threshold */336	amd_pmf_get_power_threshold();337 338	/* skin temperature limits */339	pwr_ctrl = &config_store.mode_set[AUTO_QUIET].power_control;340	pwr_ctrl->spl = output.spl_quiet;341	pwr_ctrl->sppt = output.sppt_quiet;342	pwr_ctrl->fppt = output.fppt_quiet;343	pwr_ctrl->sppt_apu_only = output.sppt_apu_only_quiet;344	pwr_ctrl->stt_min = output.stt_min_limit_quiet;345	pwr_ctrl->stt_skin_temp[STT_TEMP_APU] = output.stt_apu_quiet;346	pwr_ctrl->stt_skin_temp[STT_TEMP_HS2] = output.stt_hs2_quiet;347 348	pwr_ctrl = &config_store.mode_set[AUTO_BALANCE].power_control;349	pwr_ctrl->spl = output.spl_balanced;350	pwr_ctrl->sppt = output.sppt_balanced;351	pwr_ctrl->fppt = output.fppt_balanced;352	pwr_ctrl->sppt_apu_only = output.sppt_apu_only_balanced;353	pwr_ctrl->stt_min = output.stt_min_limit_balanced;354	pwr_ctrl->stt_skin_temp[STT_TEMP_APU] = output.stt_apu_balanced;355	pwr_ctrl->stt_skin_temp[STT_TEMP_HS2] = output.stt_hs2_balanced;356 357	pwr_ctrl = &config_store.mode_set[AUTO_PERFORMANCE].power_control;358	pwr_ctrl->spl = output.spl_perf;359	pwr_ctrl->sppt = output.sppt_perf;360	pwr_ctrl->fppt = output.fppt_perf;361	pwr_ctrl->sppt_apu_only = output.sppt_apu_only_perf;362	pwr_ctrl->stt_min = output.stt_min_limit_perf;363	pwr_ctrl->stt_skin_temp[STT_TEMP_APU] = output.stt_apu_perf;364	pwr_ctrl->stt_skin_temp[STT_TEMP_HS2] = output.stt_hs2_perf;365 366	pwr_ctrl = &config_store.mode_set[AUTO_PERFORMANCE_ON_LAP].power_control;367	pwr_ctrl->spl = output.spl_perf_on_lap;368	pwr_ctrl->sppt = output.sppt_perf_on_lap;369	pwr_ctrl->fppt = output.fppt_perf_on_lap;370	pwr_ctrl->sppt_apu_only = output.sppt_apu_only_perf_on_lap;371	pwr_ctrl->stt_min = output.stt_min_limit_perf_on_lap;372	pwr_ctrl->stt_skin_temp[STT_TEMP_APU] = output.stt_apu_perf_on_lap;373	pwr_ctrl->stt_skin_temp[STT_TEMP_HS2] = output.stt_hs2_perf_on_lap;374 375	/* Fan ID */376	config_store.mode_set[AUTO_QUIET].fan_control.fan_id = output.fan_id_quiet;377	config_store.mode_set[AUTO_BALANCE].fan_control.fan_id = output.fan_id_balanced;378	config_store.mode_set[AUTO_PERFORMANCE].fan_control.fan_id = output.fan_id_perf;379	config_store.mode_set[AUTO_PERFORMANCE_ON_LAP].fan_control.fan_id =380									output.fan_id_perf;381 382	config_store.transition[AUTO_TRANSITION_TO_QUIET].target_mode = AUTO_QUIET;383	config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].target_mode =384								AUTO_PERFORMANCE;385	config_store.transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].target_mode =386									AUTO_BALANCE;387	config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].target_mode =388									AUTO_BALANCE;389 390	config_store.transition[AUTO_TRANSITION_TO_QUIET].shifting_up = false;391	config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].shifting_up = true;392	config_store.transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].shifting_up = true;393	config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].shifting_up =394										false;395 396	for (i = 0 ; i < AUTO_MODE_MAX ; i++) {397		if (config_store.mode_set[i].fan_control.fan_id == FAN_INDEX_AUTO)398			config_store.mode_set[i].fan_control.manual = false;399		else400			config_store.mode_set[i].fan_control.manual = true;401	}402 403	/* set to initial default values */404	config_store.current_mode = AUTO_BALANCE;405	dev->socket_power_history_idx = -1;406 407	amd_pmf_dump_auto_mode_defaults(&config_store);408}409 410int amd_pmf_reset_amt(struct amd_pmf_dev *dev)411{412	/*413	 * OEM BIOS implementation guide says that if the auto mode is enabled414	 * the platform_profile registration shall be done by the OEM driver.415	 * There could be cases where both static slider and auto mode BIOS416	 * functions are enabled, in that case enable static slider updates417	 * only if it advertised as supported.418	 */419 420	if (is_apmf_func_supported(dev, APMF_FUNC_STATIC_SLIDER_GRANULAR)) {421		dev_dbg(dev->dev, "resetting AMT thermals\n");422		amd_pmf_set_sps_power_limits(dev);423	}424	return 0;425}426 427void amd_pmf_handle_amt(struct amd_pmf_dev *dev)428{429	amd_pmf_set_automode(dev, config_store.current_mode, NULL);430}431 432void amd_pmf_deinit_auto_mode(struct amd_pmf_dev *dev)433{434	cancel_delayed_work_sync(&dev->work_buffer);435}436 437void amd_pmf_init_auto_mode(struct amd_pmf_dev *dev)438{439	amd_pmf_load_defaults_auto_mode(dev);440	amd_pmf_init_metrics_table(dev);441}442