1// SPDX-License-Identifier: GPL-2.0
2/*
3 * AMD Platform Management Framework Driver
4 *
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_DEBUG
19static 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#else
109static void amd_pmf_dump_auto_mode_defaults(struct auto_mode_mode_config *data) {}
110#endif
111
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_DEBUG
184		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#endif
197	}
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_DEBUG
203	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#endif
209
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_DEBUG
262	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#endif
284}
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		else
400			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 enabled
414	 * the platform_profile registration shall be done by the OEM driver.
415	 * There could be cases where both static slider and auto mode BIOS
416	 * functions are enabled, in that case enable static slider updates
417	 * 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