xref: /openbmc/linux/drivers/platform/x86/amd/pmf/auto-mode.c (revision 2612e3bbc0386368a850140a6c9b990cd496a5ec)
13f5571d9SShyam Sundar S K // SPDX-License-Identifier: GPL-2.0
23f5571d9SShyam Sundar S K /*
33f5571d9SShyam Sundar S K  * AMD Platform Management Framework Driver
43f5571d9SShyam Sundar S K  *
53f5571d9SShyam Sundar S K  * Copyright (c) 2022, Advanced Micro Devices, Inc.
63f5571d9SShyam Sundar S K  * All Rights Reserved.
73f5571d9SShyam Sundar S K  *
83f5571d9SShyam Sundar S K  * Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
93f5571d9SShyam Sundar S K  */
103f5571d9SShyam Sundar S K 
113f5571d9SShyam Sundar S K #include <linux/acpi.h>
123f5571d9SShyam Sundar S K #include <linux/workqueue.h>
133f5571d9SShyam Sundar S K #include "pmf.h"
143f5571d9SShyam Sundar S K 
153f5571d9SShyam Sundar S K static struct auto_mode_mode_config config_store;
163f5571d9SShyam Sundar S K static const char *state_as_str(unsigned int state);
173f5571d9SShyam Sundar S K 
18a82ebb3dSShyam Sundar S K #ifdef CONFIG_AMD_PMF_DEBUG
amd_pmf_dump_auto_mode_defaults(struct auto_mode_mode_config * data)19a82ebb3dSShyam Sundar S K static void amd_pmf_dump_auto_mode_defaults(struct auto_mode_mode_config *data)
20a82ebb3dSShyam Sundar S K {
21a82ebb3dSShyam Sundar S K 	struct auto_mode_mode_settings *its_mode;
22a82ebb3dSShyam Sundar S K 
23a82ebb3dSShyam Sundar S K 	pr_debug("Auto Mode Data - BEGIN\n");
24a82ebb3dSShyam Sundar S K 
25a82ebb3dSShyam Sundar S K 	/* time constant */
26a82ebb3dSShyam Sundar S K 	pr_debug("balanced_to_perf: %u ms\n",
27a82ebb3dSShyam Sundar S K 		 data->transition[AUTO_TRANSITION_TO_PERFORMANCE].time_constant);
28a82ebb3dSShyam Sundar S K 	pr_debug("perf_to_balanced: %u ms\n",
29a82ebb3dSShyam Sundar S K 		 data->transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].time_constant);
30a82ebb3dSShyam Sundar S K 	pr_debug("quiet_to_balanced: %u ms\n",
31a82ebb3dSShyam Sundar S K 		 data->transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].time_constant);
32a82ebb3dSShyam Sundar S K 	pr_debug("balanced_to_quiet: %u ms\n",
33a82ebb3dSShyam Sundar S K 		 data->transition[AUTO_TRANSITION_TO_QUIET].time_constant);
34a82ebb3dSShyam Sundar S K 
35a82ebb3dSShyam Sundar S K 	/* power floor */
36a82ebb3dSShyam Sundar S K 	pr_debug("pfloor_perf: %u mW\n", data->mode_set[AUTO_PERFORMANCE].power_floor);
37a82ebb3dSShyam Sundar S K 	pr_debug("pfloor_balanced: %u mW\n", data->mode_set[AUTO_BALANCE].power_floor);
38a82ebb3dSShyam Sundar S K 	pr_debug("pfloor_quiet: %u mW\n", data->mode_set[AUTO_QUIET].power_floor);
39a82ebb3dSShyam Sundar S K 
40a82ebb3dSShyam Sundar S K 	/* Power delta for mode change */
41a82ebb3dSShyam Sundar S K 	pr_debug("pd_balanced_to_perf: %u mW\n",
42a82ebb3dSShyam Sundar S K 		 data->transition[AUTO_TRANSITION_TO_PERFORMANCE].power_delta);
43a82ebb3dSShyam Sundar S K 	pr_debug("pd_perf_to_balanced: %u mW\n",
44a82ebb3dSShyam Sundar S K 		 data->transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].power_delta);
45a82ebb3dSShyam Sundar S K 	pr_debug("pd_quiet_to_balanced: %u mW\n",
46a82ebb3dSShyam Sundar S K 		 data->transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].power_delta);
47a82ebb3dSShyam Sundar S K 	pr_debug("pd_balanced_to_quiet: %u mW\n",
48a82ebb3dSShyam Sundar S K 		 data->transition[AUTO_TRANSITION_TO_QUIET].power_delta);
49a82ebb3dSShyam Sundar S K 
50a82ebb3dSShyam Sundar S K 	/* skin temperature limits */
51a82ebb3dSShyam Sundar S K 	its_mode = &data->mode_set[AUTO_PERFORMANCE_ON_LAP];
52a82ebb3dSShyam Sundar S K 	pr_debug("stt_apu_perf_on_lap: %u C\n",
53a82ebb3dSShyam Sundar S K 		 its_mode->power_control.stt_skin_temp[STT_TEMP_APU]);
54a82ebb3dSShyam Sundar S K 	pr_debug("stt_hs2_perf_on_lap: %u C\n",
55a82ebb3dSShyam Sundar S K 		 its_mode->power_control.stt_skin_temp[STT_TEMP_HS2]);
56a82ebb3dSShyam Sundar S K 	pr_debug("stt_min_limit_perf_on_lap: %u mW\n", its_mode->power_control.stt_min);
57a82ebb3dSShyam Sundar S K 
58a82ebb3dSShyam Sundar S K 	its_mode = &data->mode_set[AUTO_PERFORMANCE];
59a82ebb3dSShyam Sundar S K 	pr_debug("stt_apu_perf: %u C\n", its_mode->power_control.stt_skin_temp[STT_TEMP_APU]);
60a82ebb3dSShyam Sundar S K 	pr_debug("stt_hs2_perf: %u C\n", its_mode->power_control.stt_skin_temp[STT_TEMP_HS2]);
61a82ebb3dSShyam Sundar S K 	pr_debug("stt_min_limit_perf: %u mW\n", its_mode->power_control.stt_min);
62a82ebb3dSShyam Sundar S K 
63a82ebb3dSShyam Sundar S K 	its_mode = &data->mode_set[AUTO_BALANCE];
64a82ebb3dSShyam Sundar S K 	pr_debug("stt_apu_balanced: %u C\n", its_mode->power_control.stt_skin_temp[STT_TEMP_APU]);
65a82ebb3dSShyam Sundar S K 	pr_debug("stt_hs2_balanced: %u C\n", its_mode->power_control.stt_skin_temp[STT_TEMP_HS2]);
66a82ebb3dSShyam Sundar S K 	pr_debug("stt_min_limit_balanced: %u mW\n", its_mode->power_control.stt_min);
67a82ebb3dSShyam Sundar S K 
68a82ebb3dSShyam Sundar S K 	its_mode = &data->mode_set[AUTO_QUIET];
69a82ebb3dSShyam Sundar S K 	pr_debug("stt_apu_quiet: %u C\n", its_mode->power_control.stt_skin_temp[STT_TEMP_APU]);
70a82ebb3dSShyam Sundar S K 	pr_debug("stt_hs2_quiet: %u C\n", its_mode->power_control.stt_skin_temp[STT_TEMP_HS2]);
71a82ebb3dSShyam Sundar S K 	pr_debug("stt_min_limit_quiet: %u mW\n", its_mode->power_control.stt_min);
72a82ebb3dSShyam Sundar S K 
73a82ebb3dSShyam Sundar S K 	/* SPL based power limits */
74a82ebb3dSShyam Sundar S K 	its_mode = &data->mode_set[AUTO_PERFORMANCE_ON_LAP];
75a82ebb3dSShyam Sundar S K 	pr_debug("fppt_perf_on_lap: %u mW\n", its_mode->power_control.fppt);
76a82ebb3dSShyam Sundar S K 	pr_debug("sppt_perf_on_lap: %u mW\n", its_mode->power_control.sppt);
77a82ebb3dSShyam Sundar S K 	pr_debug("spl_perf_on_lap: %u mW\n", its_mode->power_control.spl);
78a82ebb3dSShyam Sundar S K 	pr_debug("sppt_apu_only_perf_on_lap: %u mW\n", its_mode->power_control.sppt_apu_only);
79a82ebb3dSShyam Sundar S K 
80a82ebb3dSShyam Sundar S K 	its_mode = &data->mode_set[AUTO_PERFORMANCE];
81a82ebb3dSShyam Sundar S K 	pr_debug("fppt_perf: %u mW\n", its_mode->power_control.fppt);
82a82ebb3dSShyam Sundar S K 	pr_debug("sppt_perf: %u mW\n", its_mode->power_control.sppt);
83a82ebb3dSShyam Sundar S K 	pr_debug("spl_perf: %u mW\n", its_mode->power_control.spl);
84a82ebb3dSShyam Sundar S K 	pr_debug("sppt_apu_only_perf: %u mW\n", its_mode->power_control.sppt_apu_only);
85a82ebb3dSShyam Sundar S K 
86a82ebb3dSShyam Sundar S K 	its_mode = &data->mode_set[AUTO_BALANCE];
87a82ebb3dSShyam Sundar S K 	pr_debug("fppt_balanced: %u mW\n", its_mode->power_control.fppt);
88a82ebb3dSShyam Sundar S K 	pr_debug("sppt_balanced: %u mW\n", its_mode->power_control.sppt);
89a82ebb3dSShyam Sundar S K 	pr_debug("spl_balanced: %u mW\n", its_mode->power_control.spl);
90a82ebb3dSShyam Sundar S K 	pr_debug("sppt_apu_only_balanced: %u mW\n", its_mode->power_control.sppt_apu_only);
91a82ebb3dSShyam Sundar S K 
92a82ebb3dSShyam Sundar S K 	its_mode = &data->mode_set[AUTO_QUIET];
93a82ebb3dSShyam Sundar S K 	pr_debug("fppt_quiet: %u mW\n", its_mode->power_control.fppt);
94a82ebb3dSShyam Sundar S K 	pr_debug("sppt_quiet: %u mW\n", its_mode->power_control.sppt);
95a82ebb3dSShyam Sundar S K 	pr_debug("spl_quiet: %u mW\n", its_mode->power_control.spl);
96a82ebb3dSShyam Sundar S K 	pr_debug("sppt_apu_only_quiet: %u mW\n", its_mode->power_control.sppt_apu_only);
97a82ebb3dSShyam Sundar S K 
98a82ebb3dSShyam Sundar S K 	/* Fan ID */
99a82ebb3dSShyam Sundar S K 	pr_debug("fan_id_perf: %lu\n",
100a82ebb3dSShyam Sundar S K 		 data->mode_set[AUTO_PERFORMANCE].fan_control.fan_id);
101a82ebb3dSShyam Sundar S K 	pr_debug("fan_id_balanced: %lu\n",
102a82ebb3dSShyam Sundar S K 		 data->mode_set[AUTO_BALANCE].fan_control.fan_id);
103a82ebb3dSShyam Sundar S K 	pr_debug("fan_id_quiet: %lu\n",
104a82ebb3dSShyam Sundar S K 		 data->mode_set[AUTO_QUIET].fan_control.fan_id);
105a82ebb3dSShyam Sundar S K 
106a82ebb3dSShyam Sundar S K 	pr_debug("Auto Mode Data - END\n");
107a82ebb3dSShyam Sundar S K }
108a82ebb3dSShyam Sundar S K #else
amd_pmf_dump_auto_mode_defaults(struct auto_mode_mode_config * data)109a82ebb3dSShyam Sundar S K static void amd_pmf_dump_auto_mode_defaults(struct auto_mode_mode_config *data) {}
110a82ebb3dSShyam Sundar S K #endif
111a82ebb3dSShyam Sundar S K 
amd_pmf_set_automode(struct amd_pmf_dev * dev,int idx,struct auto_mode_mode_config * table)1123f5571d9SShyam Sundar S K static void amd_pmf_set_automode(struct amd_pmf_dev *dev, int idx,
1133f5571d9SShyam Sundar S K 				 struct auto_mode_mode_config *table)
1143f5571d9SShyam Sundar S K {
1153f5571d9SShyam Sundar S K 	struct power_table_control *pwr_ctrl = &config_store.mode_set[idx].power_control;
1163f5571d9SShyam Sundar S K 
1173f5571d9SShyam Sundar S K 	amd_pmf_send_cmd(dev, SET_SPL, false, pwr_ctrl->spl, NULL);
1183f5571d9SShyam Sundar S K 	amd_pmf_send_cmd(dev, SET_FPPT, false, pwr_ctrl->fppt, NULL);
1193f5571d9SShyam Sundar S K 	amd_pmf_send_cmd(dev, SET_SPPT, false, pwr_ctrl->sppt, NULL);
1203f5571d9SShyam Sundar S K 	amd_pmf_send_cmd(dev, SET_SPPT_APU_ONLY, false, pwr_ctrl->sppt_apu_only, NULL);
1213f5571d9SShyam Sundar S K 	amd_pmf_send_cmd(dev, SET_STT_MIN_LIMIT, false, pwr_ctrl->stt_min, NULL);
1223f5571d9SShyam Sundar S K 	amd_pmf_send_cmd(dev, SET_STT_LIMIT_APU, false,
1233f5571d9SShyam Sundar S K 			 pwr_ctrl->stt_skin_temp[STT_TEMP_APU], NULL);
1243f5571d9SShyam Sundar S K 	amd_pmf_send_cmd(dev, SET_STT_LIMIT_HS2, false,
1253f5571d9SShyam Sundar S K 			 pwr_ctrl->stt_skin_temp[STT_TEMP_HS2], NULL);
1263f5571d9SShyam Sundar S K 
1273f5571d9SShyam Sundar S K 	if (is_apmf_func_supported(dev, APMF_FUNC_SET_FAN_IDX))
1283f5571d9SShyam Sundar S K 		apmf_update_fan_idx(dev, config_store.mode_set[idx].fan_control.manual,
1293f5571d9SShyam Sundar S K 				    config_store.mode_set[idx].fan_control.fan_id);
1303f5571d9SShyam Sundar S K }
1313f5571d9SShyam Sundar S K 
amd_pmf_get_moving_avg(struct amd_pmf_dev * pdev,int socket_power)1323f5571d9SShyam Sundar S K static int amd_pmf_get_moving_avg(struct amd_pmf_dev *pdev, int socket_power)
1333f5571d9SShyam Sundar S K {
1343f5571d9SShyam Sundar S K 	int i, total = 0;
1353f5571d9SShyam Sundar S K 
1363f5571d9SShyam Sundar S K 	if (pdev->socket_power_history_idx == -1) {
1373f5571d9SShyam Sundar S K 		for (i = 0; i < AVG_SAMPLE_SIZE; i++)
1383f5571d9SShyam Sundar S K 			pdev->socket_power_history[i] = socket_power;
1393f5571d9SShyam Sundar S K 	}
1403f5571d9SShyam Sundar S K 
1413f5571d9SShyam Sundar S K 	pdev->socket_power_history_idx = (pdev->socket_power_history_idx + 1) % AVG_SAMPLE_SIZE;
1423f5571d9SShyam Sundar S K 	pdev->socket_power_history[pdev->socket_power_history_idx] = socket_power;
1433f5571d9SShyam Sundar S K 
1443f5571d9SShyam Sundar S K 	for (i = 0; i < AVG_SAMPLE_SIZE; i++)
1453f5571d9SShyam Sundar S K 		total += pdev->socket_power_history[i];
1463f5571d9SShyam Sundar S K 
1473f5571d9SShyam Sundar S K 	return total / AVG_SAMPLE_SIZE;
1483f5571d9SShyam Sundar S K }
1493f5571d9SShyam Sundar S K 
amd_pmf_trans_automode(struct amd_pmf_dev * dev,int socket_power,ktime_t time_elapsed_ms)1503f5571d9SShyam Sundar S K void amd_pmf_trans_automode(struct amd_pmf_dev *dev, int socket_power, ktime_t time_elapsed_ms)
1513f5571d9SShyam Sundar S K {
1523f5571d9SShyam Sundar S K 	int avg_power = 0;
1533f5571d9SShyam Sundar S K 	bool update = false;
1543f5571d9SShyam Sundar S K 	int i, j;
1553f5571d9SShyam Sundar S K 
1563f5571d9SShyam Sundar S K 	/* Get the average moving average computed by auto mode algorithm */
1573f5571d9SShyam Sundar S K 	avg_power = amd_pmf_get_moving_avg(dev, socket_power);
1583f5571d9SShyam Sundar S K 
1593f5571d9SShyam Sundar S K 	for (i = 0; i < AUTO_TRANSITION_MAX; i++) {
1603f5571d9SShyam Sundar S K 		if ((config_store.transition[i].shifting_up && avg_power >=
1613f5571d9SShyam Sundar S K 		     config_store.transition[i].power_threshold) ||
1623f5571d9SShyam Sundar S K 		    (!config_store.transition[i].shifting_up && avg_power <=
1633f5571d9SShyam Sundar S K 		     config_store.transition[i].power_threshold)) {
1643f5571d9SShyam Sundar S K 			if (config_store.transition[i].timer <
1653f5571d9SShyam Sundar S K 			    config_store.transition[i].time_constant)
1663f5571d9SShyam Sundar S K 				config_store.transition[i].timer += time_elapsed_ms;
1673f5571d9SShyam Sundar S K 		} else {
1683f5571d9SShyam Sundar S K 			config_store.transition[i].timer = 0;
1693f5571d9SShyam Sundar S K 		}
1703f5571d9SShyam Sundar S K 
1713f5571d9SShyam Sundar S K 		if (config_store.transition[i].timer >=
1723f5571d9SShyam Sundar S K 		    config_store.transition[i].time_constant &&
1733f5571d9SShyam Sundar S K 		    !config_store.transition[i].applied) {
1743f5571d9SShyam Sundar S K 			config_store.transition[i].applied = true;
1753f5571d9SShyam Sundar S K 			update = true;
1763f5571d9SShyam Sundar S K 		} else if (config_store.transition[i].timer <=
1773f5571d9SShyam Sundar S K 			   config_store.transition[i].time_constant &&
1783f5571d9SShyam Sundar S K 			   config_store.transition[i].applied) {
1793f5571d9SShyam Sundar S K 			config_store.transition[i].applied = false;
1803f5571d9SShyam Sundar S K 			update = true;
1813f5571d9SShyam Sundar S K 		}
182*63b5dbfdSShyam Sundar S K 
183*63b5dbfdSShyam Sundar S K #ifdef CONFIG_AMD_PMF_DEBUG
184*63b5dbfdSShyam Sundar S K 		dev_dbg(dev->dev, "[AUTO MODE] average_power : %d mW mode: %s\n", avg_power,
185*63b5dbfdSShyam Sundar S K 			state_as_str(config_store.current_mode));
186*63b5dbfdSShyam Sundar S K 
187*63b5dbfdSShyam Sundar S K 		dev_dbg(dev->dev, "[AUTO MODE] time: %lld ms timer: %u ms tc: %u ms\n",
188*63b5dbfdSShyam Sundar S K 			time_elapsed_ms, config_store.transition[i].timer,
189*63b5dbfdSShyam Sundar S K 			config_store.transition[i].time_constant);
190*63b5dbfdSShyam Sundar S K 
191*63b5dbfdSShyam Sundar S K 		dev_dbg(dev->dev, "[AUTO MODE] shiftup: %u pt: %u mW pf: %u mW pd: %u mW\n",
192*63b5dbfdSShyam Sundar S K 			config_store.transition[i].shifting_up,
193*63b5dbfdSShyam Sundar S K 			config_store.transition[i].power_threshold,
194*63b5dbfdSShyam Sundar S K 			config_store.mode_set[i].power_floor,
195*63b5dbfdSShyam Sundar S K 			config_store.transition[i].power_delta);
196*63b5dbfdSShyam Sundar S K #endif
1973f5571d9SShyam Sundar S K 	}
1983f5571d9SShyam Sundar S K 
1993f5571d9SShyam Sundar S K 	dev_dbg(dev->dev, "[AUTO_MODE] avg power: %u mW mode: %s\n", avg_power,
2003f5571d9SShyam Sundar S K 		state_as_str(config_store.current_mode));
2013f5571d9SShyam Sundar S K 
202*63b5dbfdSShyam Sundar S K #ifdef CONFIG_AMD_PMF_DEBUG
203*63b5dbfdSShyam Sundar S K 	dev_dbg(dev->dev, "[AUTO MODE] priority1: %u priority2: %u priority3: %u priority4: %u\n",
204*63b5dbfdSShyam Sundar S K 		config_store.transition[0].applied,
205*63b5dbfdSShyam Sundar S K 		config_store.transition[1].applied,
206*63b5dbfdSShyam Sundar S K 		config_store.transition[2].applied,
207*63b5dbfdSShyam Sundar S K 		config_store.transition[3].applied);
208*63b5dbfdSShyam Sundar S K #endif
209*63b5dbfdSShyam Sundar S K 
2103f5571d9SShyam Sundar S K 	if (update) {
2113f5571d9SShyam Sundar S K 		for (j = 0; j < AUTO_TRANSITION_MAX; j++) {
2123f5571d9SShyam Sundar S K 			/* Apply the mode with highest priority indentified */
2133f5571d9SShyam Sundar S K 			if (config_store.transition[j].applied) {
2143f5571d9SShyam Sundar S K 				if (config_store.current_mode !=
2153f5571d9SShyam Sundar S K 				    config_store.transition[j].target_mode) {
2163f5571d9SShyam Sundar S K 					config_store.current_mode =
2173f5571d9SShyam Sundar S K 							config_store.transition[j].target_mode;
2183f5571d9SShyam Sundar S K 					dev_dbg(dev->dev, "[AUTO_MODE] moving to mode:%s\n",
2193f5571d9SShyam Sundar S K 						state_as_str(config_store.current_mode));
2203f5571d9SShyam Sundar S K 					amd_pmf_set_automode(dev, config_store.current_mode, NULL);
2213f5571d9SShyam Sundar S K 				}
2223f5571d9SShyam Sundar S K 				break;
2233f5571d9SShyam Sundar S K 			}
2243f5571d9SShyam Sundar S K 		}
2253f5571d9SShyam Sundar S K 	}
2263f5571d9SShyam Sundar S K }
2273f5571d9SShyam Sundar S K 
amd_pmf_update_2_cql(struct amd_pmf_dev * dev,bool is_cql_event)2287d77dcc8SShyam Sundar S K void amd_pmf_update_2_cql(struct amd_pmf_dev *dev, bool is_cql_event)
2297d77dcc8SShyam Sundar S K {
2307d77dcc8SShyam Sundar S K 	int mode = config_store.current_mode;
2317d77dcc8SShyam Sundar S K 
2327d77dcc8SShyam Sundar S K 	config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].target_mode =
2337d77dcc8SShyam Sundar S K 				   is_cql_event ? AUTO_PERFORMANCE_ON_LAP : AUTO_PERFORMANCE;
2347d77dcc8SShyam Sundar S K 
2357d77dcc8SShyam Sundar S K 	if ((mode == AUTO_PERFORMANCE || mode == AUTO_PERFORMANCE_ON_LAP) &&
2367d77dcc8SShyam Sundar S K 	    mode != config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].target_mode) {
2377d77dcc8SShyam Sundar S K 		mode = config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].target_mode;
2387d77dcc8SShyam Sundar S K 		amd_pmf_set_automode(dev, mode, NULL);
2397d77dcc8SShyam Sundar S K 	}
2407d77dcc8SShyam Sundar S K 	dev_dbg(dev->dev, "updated CQL thermals\n");
2417d77dcc8SShyam Sundar S K }
2427d77dcc8SShyam Sundar S K 
amd_pmf_get_power_threshold(void)2433f5571d9SShyam Sundar S K static void amd_pmf_get_power_threshold(void)
2443f5571d9SShyam Sundar S K {
2453f5571d9SShyam Sundar S K 	config_store.transition[AUTO_TRANSITION_TO_QUIET].power_threshold =
2463f5571d9SShyam Sundar S K 				config_store.mode_set[AUTO_BALANCE].power_floor -
2473f5571d9SShyam Sundar S K 				config_store.transition[AUTO_TRANSITION_TO_QUIET].power_delta;
2483f5571d9SShyam Sundar S K 
2493f5571d9SShyam Sundar S K 	config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].power_threshold =
2503f5571d9SShyam Sundar S K 				config_store.mode_set[AUTO_BALANCE].power_floor -
2513f5571d9SShyam Sundar S K 				config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].power_delta;
2523f5571d9SShyam Sundar S K 
2533f5571d9SShyam Sundar S K 	config_store.transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].power_threshold =
2543f5571d9SShyam Sundar S K 			config_store.mode_set[AUTO_QUIET].power_floor -
2553f5571d9SShyam Sundar S K 			config_store.transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].power_delta;
2563f5571d9SShyam Sundar S K 
2573f5571d9SShyam Sundar S K 	config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].power_threshold =
2583f5571d9SShyam Sundar S K 		config_store.mode_set[AUTO_PERFORMANCE].power_floor -
2593f5571d9SShyam Sundar S K 		config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].power_delta;
260a82ebb3dSShyam Sundar S K 
261a82ebb3dSShyam Sundar S K #ifdef CONFIG_AMD_PMF_DEBUG
262a82ebb3dSShyam Sundar S K 	pr_debug("[AUTO MODE TO_QUIET] pt: %u mW pf: %u mW pd: %u mW\n",
263a82ebb3dSShyam Sundar S K 		 config_store.transition[AUTO_TRANSITION_TO_QUIET].power_threshold,
264a82ebb3dSShyam Sundar S K 		 config_store.mode_set[AUTO_BALANCE].power_floor,
265a82ebb3dSShyam Sundar S K 		 config_store.transition[AUTO_TRANSITION_TO_QUIET].power_delta);
266a82ebb3dSShyam Sundar S K 
267a82ebb3dSShyam Sundar S K 	pr_debug("[AUTO MODE TO_PERFORMANCE] pt: %u mW pf: %u mW pd: %u mW\n",
268a82ebb3dSShyam Sundar S K 		 config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].power_threshold,
269a82ebb3dSShyam Sundar S K 		 config_store.mode_set[AUTO_BALANCE].power_floor,
270a82ebb3dSShyam Sundar S K 		 config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].power_delta);
271a82ebb3dSShyam Sundar S K 
272a82ebb3dSShyam Sundar S K 	pr_debug("[AUTO MODE QUIET_TO_BALANCE] pt: %u mW pf: %u mW pd: %u mW\n",
273a82ebb3dSShyam Sundar S K 		 config_store.transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE]
274a82ebb3dSShyam Sundar S K 		 .power_threshold,
275a82ebb3dSShyam Sundar S K 		 config_store.mode_set[AUTO_QUIET].power_floor,
276a82ebb3dSShyam Sundar S K 		 config_store.transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].power_delta);
277a82ebb3dSShyam Sundar S K 
278a82ebb3dSShyam Sundar S K 	pr_debug("[AUTO MODE PERFORMANCE_TO_BALANCE] pt: %u mW pf: %u mW pd: %u mW\n",
279a82ebb3dSShyam Sundar S K 		 config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE]
280a82ebb3dSShyam Sundar S K 		 .power_threshold,
281a82ebb3dSShyam Sundar S K 		 config_store.mode_set[AUTO_PERFORMANCE].power_floor,
282a82ebb3dSShyam Sundar S K 		 config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].power_delta);
283a82ebb3dSShyam Sundar S K #endif
2843f5571d9SShyam Sundar S K }
2853f5571d9SShyam Sundar S K 
state_as_str(unsigned int state)2863f5571d9SShyam Sundar S K static const char *state_as_str(unsigned int state)
2873f5571d9SShyam Sundar S K {
2883f5571d9SShyam Sundar S K 	switch (state) {
2893f5571d9SShyam Sundar S K 	case AUTO_QUIET:
2903f5571d9SShyam Sundar S K 		return "QUIET";
2913f5571d9SShyam Sundar S K 	case AUTO_BALANCE:
2923f5571d9SShyam Sundar S K 		return "BALANCED";
2933f5571d9SShyam Sundar S K 	case AUTO_PERFORMANCE_ON_LAP:
2943f5571d9SShyam Sundar S K 		return "ON_LAP";
2953f5571d9SShyam Sundar S K 	case AUTO_PERFORMANCE:
2963f5571d9SShyam Sundar S K 		return "PERFORMANCE";
2973f5571d9SShyam Sundar S K 	default:
2983f5571d9SShyam Sundar S K 		return "Unknown Auto Mode State";
2993f5571d9SShyam Sundar S K 	}
3003f5571d9SShyam Sundar S K }
3013f5571d9SShyam Sundar S K 
amd_pmf_load_defaults_auto_mode(struct amd_pmf_dev * dev)3023f5571d9SShyam Sundar S K static void amd_pmf_load_defaults_auto_mode(struct amd_pmf_dev *dev)
3033f5571d9SShyam Sundar S K {
3043f5571d9SShyam Sundar S K 	struct apmf_auto_mode output;
3053f5571d9SShyam Sundar S K 	struct power_table_control *pwr_ctrl;
3063f5571d9SShyam Sundar S K 	int i;
3073f5571d9SShyam Sundar S K 
3083f5571d9SShyam Sundar S K 	apmf_get_auto_mode_def(dev, &output);
3093f5571d9SShyam Sundar S K 	/* time constant */
3103f5571d9SShyam Sundar S K 	config_store.transition[AUTO_TRANSITION_TO_QUIET].time_constant =
3113f5571d9SShyam Sundar S K 								output.balanced_to_quiet;
3123f5571d9SShyam Sundar S K 	config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].time_constant =
3133f5571d9SShyam Sundar S K 								output.balanced_to_perf;
3143f5571d9SShyam Sundar S K 	config_store.transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].time_constant =
3153f5571d9SShyam Sundar S K 								output.quiet_to_balanced;
3163f5571d9SShyam Sundar S K 	config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].time_constant =
3173f5571d9SShyam Sundar S K 								output.perf_to_balanced;
3183f5571d9SShyam Sundar S K 
3193f5571d9SShyam Sundar S K 	/* power floor */
3203f5571d9SShyam Sundar S K 	config_store.mode_set[AUTO_QUIET].power_floor = output.pfloor_quiet;
3213f5571d9SShyam Sundar S K 	config_store.mode_set[AUTO_BALANCE].power_floor = output.pfloor_balanced;
3223f5571d9SShyam Sundar S K 	config_store.mode_set[AUTO_PERFORMANCE].power_floor = output.pfloor_perf;
3233f5571d9SShyam Sundar S K 	config_store.mode_set[AUTO_PERFORMANCE_ON_LAP].power_floor = output.pfloor_perf;
3243f5571d9SShyam Sundar S K 
3253f5571d9SShyam Sundar S K 	/* Power delta for mode change */
3263f5571d9SShyam Sundar S K 	config_store.transition[AUTO_TRANSITION_TO_QUIET].power_delta =
3273f5571d9SShyam Sundar S K 								output.pd_balanced_to_quiet;
3283f5571d9SShyam Sundar S K 	config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].power_delta =
3293f5571d9SShyam Sundar S K 								output.pd_balanced_to_perf;
3303f5571d9SShyam Sundar S K 	config_store.transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].power_delta =
3313f5571d9SShyam Sundar S K 								output.pd_quiet_to_balanced;
3323f5571d9SShyam Sundar S K 	config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].power_delta =
3333f5571d9SShyam Sundar S K 								output.pd_perf_to_balanced;
3343f5571d9SShyam Sundar S K 
3353f5571d9SShyam Sundar S K 	/* Power threshold */
3363f5571d9SShyam Sundar S K 	amd_pmf_get_power_threshold();
3373f5571d9SShyam Sundar S K 
3383f5571d9SShyam Sundar S K 	/* skin temperature limits */
3393f5571d9SShyam Sundar S K 	pwr_ctrl = &config_store.mode_set[AUTO_QUIET].power_control;
3403f5571d9SShyam Sundar S K 	pwr_ctrl->spl = output.spl_quiet;
3413f5571d9SShyam Sundar S K 	pwr_ctrl->sppt = output.sppt_quiet;
3423f5571d9SShyam Sundar S K 	pwr_ctrl->fppt = output.fppt_quiet;
3433f5571d9SShyam Sundar S K 	pwr_ctrl->sppt_apu_only = output.sppt_apu_only_quiet;
3443f5571d9SShyam Sundar S K 	pwr_ctrl->stt_min = output.stt_min_limit_quiet;
3453f5571d9SShyam Sundar S K 	pwr_ctrl->stt_skin_temp[STT_TEMP_APU] = output.stt_apu_quiet;
3463f5571d9SShyam Sundar S K 	pwr_ctrl->stt_skin_temp[STT_TEMP_HS2] = output.stt_hs2_quiet;
3473f5571d9SShyam Sundar S K 
3483f5571d9SShyam Sundar S K 	pwr_ctrl = &config_store.mode_set[AUTO_BALANCE].power_control;
3493f5571d9SShyam Sundar S K 	pwr_ctrl->spl = output.spl_balanced;
3503f5571d9SShyam Sundar S K 	pwr_ctrl->sppt = output.sppt_balanced;
3513f5571d9SShyam Sundar S K 	pwr_ctrl->fppt = output.fppt_balanced;
3523f5571d9SShyam Sundar S K 	pwr_ctrl->sppt_apu_only = output.sppt_apu_only_balanced;
3533f5571d9SShyam Sundar S K 	pwr_ctrl->stt_min = output.stt_min_limit_balanced;
3543f5571d9SShyam Sundar S K 	pwr_ctrl->stt_skin_temp[STT_TEMP_APU] = output.stt_apu_balanced;
3553f5571d9SShyam Sundar S K 	pwr_ctrl->stt_skin_temp[STT_TEMP_HS2] = output.stt_hs2_balanced;
3563f5571d9SShyam Sundar S K 
3573f5571d9SShyam Sundar S K 	pwr_ctrl = &config_store.mode_set[AUTO_PERFORMANCE].power_control;
3583f5571d9SShyam Sundar S K 	pwr_ctrl->spl = output.spl_perf;
3593f5571d9SShyam Sundar S K 	pwr_ctrl->sppt = output.sppt_perf;
3603f5571d9SShyam Sundar S K 	pwr_ctrl->fppt = output.fppt_perf;
3613f5571d9SShyam Sundar S K 	pwr_ctrl->sppt_apu_only = output.sppt_apu_only_perf;
3623f5571d9SShyam Sundar S K 	pwr_ctrl->stt_min = output.stt_min_limit_perf;
3633f5571d9SShyam Sundar S K 	pwr_ctrl->stt_skin_temp[STT_TEMP_APU] = output.stt_apu_perf;
3643f5571d9SShyam Sundar S K 	pwr_ctrl->stt_skin_temp[STT_TEMP_HS2] = output.stt_hs2_perf;
3653f5571d9SShyam Sundar S K 
3663f5571d9SShyam Sundar S K 	pwr_ctrl = &config_store.mode_set[AUTO_PERFORMANCE_ON_LAP].power_control;
3673f5571d9SShyam Sundar S K 	pwr_ctrl->spl = output.spl_perf_on_lap;
3683f5571d9SShyam Sundar S K 	pwr_ctrl->sppt = output.sppt_perf_on_lap;
3693f5571d9SShyam Sundar S K 	pwr_ctrl->fppt = output.fppt_perf_on_lap;
3703f5571d9SShyam Sundar S K 	pwr_ctrl->sppt_apu_only = output.sppt_apu_only_perf_on_lap;
3713f5571d9SShyam Sundar S K 	pwr_ctrl->stt_min = output.stt_min_limit_perf_on_lap;
3723f5571d9SShyam Sundar S K 	pwr_ctrl->stt_skin_temp[STT_TEMP_APU] = output.stt_apu_perf_on_lap;
3733f5571d9SShyam Sundar S K 	pwr_ctrl->stt_skin_temp[STT_TEMP_HS2] = output.stt_hs2_perf_on_lap;
3743f5571d9SShyam Sundar S K 
3753f5571d9SShyam Sundar S K 	/* Fan ID */
3763f5571d9SShyam Sundar S K 	config_store.mode_set[AUTO_QUIET].fan_control.fan_id = output.fan_id_quiet;
3773f5571d9SShyam Sundar S K 	config_store.mode_set[AUTO_BALANCE].fan_control.fan_id = output.fan_id_balanced;
3783f5571d9SShyam Sundar S K 	config_store.mode_set[AUTO_PERFORMANCE].fan_control.fan_id = output.fan_id_perf;
3793f5571d9SShyam Sundar S K 	config_store.mode_set[AUTO_PERFORMANCE_ON_LAP].fan_control.fan_id =
3803f5571d9SShyam Sundar S K 									output.fan_id_perf;
3813f5571d9SShyam Sundar S K 
3823f5571d9SShyam Sundar S K 	config_store.transition[AUTO_TRANSITION_TO_QUIET].target_mode = AUTO_QUIET;
3833f5571d9SShyam Sundar S K 	config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].target_mode =
3843f5571d9SShyam Sundar S K 								AUTO_PERFORMANCE;
3853f5571d9SShyam Sundar S K 	config_store.transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].target_mode =
3863f5571d9SShyam Sundar S K 									AUTO_BALANCE;
3873f5571d9SShyam Sundar S K 	config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].target_mode =
3883f5571d9SShyam Sundar S K 									AUTO_BALANCE;
3893f5571d9SShyam Sundar S K 
3903f5571d9SShyam Sundar S K 	config_store.transition[AUTO_TRANSITION_TO_QUIET].shifting_up = false;
3913f5571d9SShyam Sundar S K 	config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].shifting_up = true;
3923f5571d9SShyam Sundar S K 	config_store.transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].shifting_up = true;
3933f5571d9SShyam Sundar S K 	config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].shifting_up =
3943f5571d9SShyam Sundar S K 										false;
3953f5571d9SShyam Sundar S K 
3963f5571d9SShyam Sundar S K 	for (i = 0 ; i < AUTO_MODE_MAX ; i++) {
3973f5571d9SShyam Sundar S K 		if (config_store.mode_set[i].fan_control.fan_id == FAN_INDEX_AUTO)
3983f5571d9SShyam Sundar S K 			config_store.mode_set[i].fan_control.manual = false;
3993f5571d9SShyam Sundar S K 		else
4003f5571d9SShyam Sundar S K 			config_store.mode_set[i].fan_control.manual = true;
4013f5571d9SShyam Sundar S K 	}
4023f5571d9SShyam Sundar S K 
4033f5571d9SShyam Sundar S K 	/* set to initial default values */
4043f5571d9SShyam Sundar S K 	config_store.current_mode = AUTO_BALANCE;
4053f5571d9SShyam Sundar S K 	dev->socket_power_history_idx = -1;
406a82ebb3dSShyam Sundar S K 
407a82ebb3dSShyam Sundar S K 	amd_pmf_dump_auto_mode_defaults(&config_store);
4083f5571d9SShyam Sundar S K }
4093f5571d9SShyam Sundar S K 
amd_pmf_reset_amt(struct amd_pmf_dev * dev)410ea522b80SShyam Sundar S K int amd_pmf_reset_amt(struct amd_pmf_dev *dev)
4117d77dcc8SShyam Sundar S K {
4127d77dcc8SShyam Sundar S K 	/*
4137d77dcc8SShyam Sundar S K 	 * OEM BIOS implementation guide says that if the auto mode is enabled
4147d77dcc8SShyam Sundar S K 	 * the platform_profile registration shall be done by the OEM driver.
4157d77dcc8SShyam Sundar S K 	 * There could be cases where both static slider and auto mode BIOS
4167d77dcc8SShyam Sundar S K 	 * functions are enabled, in that case enable static slider updates
4177d77dcc8SShyam Sundar S K 	 * only if it advertised as supported.
4187d77dcc8SShyam Sundar S K 	 */
4197d77dcc8SShyam Sundar S K 
4207d77dcc8SShyam Sundar S K 	if (is_apmf_func_supported(dev, APMF_FUNC_STATIC_SLIDER_GRANULAR)) {
4217d77dcc8SShyam Sundar S K 		dev_dbg(dev->dev, "resetting AMT thermals\n");
422c5258d39SShyam Sundar S K 		amd_pmf_set_sps_power_limits(dev);
4237d77dcc8SShyam Sundar S K 	}
424ea522b80SShyam Sundar S K 	return 0;
4257d77dcc8SShyam Sundar S K }
4267d77dcc8SShyam Sundar S K 
amd_pmf_handle_amt(struct amd_pmf_dev * dev)4277d77dcc8SShyam Sundar S K void amd_pmf_handle_amt(struct amd_pmf_dev *dev)
4287d77dcc8SShyam Sundar S K {
4297d77dcc8SShyam Sundar S K 	amd_pmf_set_automode(dev, config_store.current_mode, NULL);
4307d77dcc8SShyam Sundar S K }
4317d77dcc8SShyam Sundar S K 
amd_pmf_deinit_auto_mode(struct amd_pmf_dev * dev)4323f5571d9SShyam Sundar S K void amd_pmf_deinit_auto_mode(struct amd_pmf_dev *dev)
4333f5571d9SShyam Sundar S K {
4343f5571d9SShyam Sundar S K 	cancel_delayed_work_sync(&dev->work_buffer);
4353f5571d9SShyam Sundar S K }
4363f5571d9SShyam Sundar S K 
amd_pmf_init_auto_mode(struct amd_pmf_dev * dev)4373f5571d9SShyam Sundar S K void amd_pmf_init_auto_mode(struct amd_pmf_dev *dev)
4383f5571d9SShyam Sundar S K {
4393f5571d9SShyam Sundar S K 	amd_pmf_load_defaults_auto_mode(dev);
4403f5571d9SShyam Sundar S K 	amd_pmf_init_metrics_table(dev);
4413f5571d9SShyam Sundar S K }
442