Loading...
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
18static void amd_pmf_set_automode(struct amd_pmf_dev *dev, int idx,
19 struct auto_mode_mode_config *table)
20{
21 struct power_table_control *pwr_ctrl = &config_store.mode_set[idx].power_control;
22
23 amd_pmf_send_cmd(dev, SET_SPL, false, pwr_ctrl->spl, NULL);
24 amd_pmf_send_cmd(dev, SET_FPPT, false, pwr_ctrl->fppt, NULL);
25 amd_pmf_send_cmd(dev, SET_SPPT, false, pwr_ctrl->sppt, NULL);
26 amd_pmf_send_cmd(dev, SET_SPPT_APU_ONLY, false, pwr_ctrl->sppt_apu_only, NULL);
27 amd_pmf_send_cmd(dev, SET_STT_MIN_LIMIT, false, pwr_ctrl->stt_min, NULL);
28 amd_pmf_send_cmd(dev, SET_STT_LIMIT_APU, false,
29 pwr_ctrl->stt_skin_temp[STT_TEMP_APU], NULL);
30 amd_pmf_send_cmd(dev, SET_STT_LIMIT_HS2, false,
31 pwr_ctrl->stt_skin_temp[STT_TEMP_HS2], NULL);
32
33 if (is_apmf_func_supported(dev, APMF_FUNC_SET_FAN_IDX))
34 apmf_update_fan_idx(dev, config_store.mode_set[idx].fan_control.manual,
35 config_store.mode_set[idx].fan_control.fan_id);
36}
37
38static int amd_pmf_get_moving_avg(struct amd_pmf_dev *pdev, int socket_power)
39{
40 int i, total = 0;
41
42 if (pdev->socket_power_history_idx == -1) {
43 for (i = 0; i < AVG_SAMPLE_SIZE; i++)
44 pdev->socket_power_history[i] = socket_power;
45 }
46
47 pdev->socket_power_history_idx = (pdev->socket_power_history_idx + 1) % AVG_SAMPLE_SIZE;
48 pdev->socket_power_history[pdev->socket_power_history_idx] = socket_power;
49
50 for (i = 0; i < AVG_SAMPLE_SIZE; i++)
51 total += pdev->socket_power_history[i];
52
53 return total / AVG_SAMPLE_SIZE;
54}
55
56void amd_pmf_trans_automode(struct amd_pmf_dev *dev, int socket_power, ktime_t time_elapsed_ms)
57{
58 int avg_power = 0;
59 bool update = false;
60 int i, j;
61
62 /* Get the average moving average computed by auto mode algorithm */
63 avg_power = amd_pmf_get_moving_avg(dev, socket_power);
64
65 for (i = 0; i < AUTO_TRANSITION_MAX; i++) {
66 if ((config_store.transition[i].shifting_up && avg_power >=
67 config_store.transition[i].power_threshold) ||
68 (!config_store.transition[i].shifting_up && avg_power <=
69 config_store.transition[i].power_threshold)) {
70 if (config_store.transition[i].timer <
71 config_store.transition[i].time_constant)
72 config_store.transition[i].timer += time_elapsed_ms;
73 } else {
74 config_store.transition[i].timer = 0;
75 }
76
77 if (config_store.transition[i].timer >=
78 config_store.transition[i].time_constant &&
79 !config_store.transition[i].applied) {
80 config_store.transition[i].applied = true;
81 update = true;
82 } else if (config_store.transition[i].timer <=
83 config_store.transition[i].time_constant &&
84 config_store.transition[i].applied) {
85 config_store.transition[i].applied = false;
86 update = true;
87 }
88 }
89
90 dev_dbg(dev->dev, "[AUTO_MODE] avg power: %u mW mode: %s\n", avg_power,
91 state_as_str(config_store.current_mode));
92
93 if (update) {
94 for (j = 0; j < AUTO_TRANSITION_MAX; j++) {
95 /* Apply the mode with highest priority indentified */
96 if (config_store.transition[j].applied) {
97 if (config_store.current_mode !=
98 config_store.transition[j].target_mode) {
99 config_store.current_mode =
100 config_store.transition[j].target_mode;
101 dev_dbg(dev->dev, "[AUTO_MODE] moving to mode:%s\n",
102 state_as_str(config_store.current_mode));
103 amd_pmf_set_automode(dev, config_store.current_mode, NULL);
104 }
105 break;
106 }
107 }
108 }
109}
110
111void amd_pmf_update_2_cql(struct amd_pmf_dev *dev, bool is_cql_event)
112{
113 int mode = config_store.current_mode;
114
115 config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].target_mode =
116 is_cql_event ? AUTO_PERFORMANCE_ON_LAP : AUTO_PERFORMANCE;
117
118 if ((mode == AUTO_PERFORMANCE || mode == AUTO_PERFORMANCE_ON_LAP) &&
119 mode != config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].target_mode) {
120 mode = config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].target_mode;
121 amd_pmf_set_automode(dev, mode, NULL);
122 }
123 dev_dbg(dev->dev, "updated CQL thermals\n");
124}
125
126static void amd_pmf_get_power_threshold(void)
127{
128 config_store.transition[AUTO_TRANSITION_TO_QUIET].power_threshold =
129 config_store.mode_set[AUTO_BALANCE].power_floor -
130 config_store.transition[AUTO_TRANSITION_TO_QUIET].power_delta;
131
132 config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].power_threshold =
133 config_store.mode_set[AUTO_BALANCE].power_floor -
134 config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].power_delta;
135
136 config_store.transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].power_threshold =
137 config_store.mode_set[AUTO_QUIET].power_floor -
138 config_store.transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].power_delta;
139
140 config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].power_threshold =
141 config_store.mode_set[AUTO_PERFORMANCE].power_floor -
142 config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].power_delta;
143}
144
145static const char *state_as_str(unsigned int state)
146{
147 switch (state) {
148 case AUTO_QUIET:
149 return "QUIET";
150 case AUTO_BALANCE:
151 return "BALANCED";
152 case AUTO_PERFORMANCE_ON_LAP:
153 return "ON_LAP";
154 case AUTO_PERFORMANCE:
155 return "PERFORMANCE";
156 default:
157 return "Unknown Auto Mode State";
158 }
159}
160
161static void amd_pmf_load_defaults_auto_mode(struct amd_pmf_dev *dev)
162{
163 struct apmf_auto_mode output;
164 struct power_table_control *pwr_ctrl;
165 int i;
166
167 apmf_get_auto_mode_def(dev, &output);
168 /* time constant */
169 config_store.transition[AUTO_TRANSITION_TO_QUIET].time_constant =
170 output.balanced_to_quiet;
171 config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].time_constant =
172 output.balanced_to_perf;
173 config_store.transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].time_constant =
174 output.quiet_to_balanced;
175 config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].time_constant =
176 output.perf_to_balanced;
177
178 /* power floor */
179 config_store.mode_set[AUTO_QUIET].power_floor = output.pfloor_quiet;
180 config_store.mode_set[AUTO_BALANCE].power_floor = output.pfloor_balanced;
181 config_store.mode_set[AUTO_PERFORMANCE].power_floor = output.pfloor_perf;
182 config_store.mode_set[AUTO_PERFORMANCE_ON_LAP].power_floor = output.pfloor_perf;
183
184 /* Power delta for mode change */
185 config_store.transition[AUTO_TRANSITION_TO_QUIET].power_delta =
186 output.pd_balanced_to_quiet;
187 config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].power_delta =
188 output.pd_balanced_to_perf;
189 config_store.transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].power_delta =
190 output.pd_quiet_to_balanced;
191 config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].power_delta =
192 output.pd_perf_to_balanced;
193
194 /* Power threshold */
195 amd_pmf_get_power_threshold();
196
197 /* skin temperature limits */
198 pwr_ctrl = &config_store.mode_set[AUTO_QUIET].power_control;
199 pwr_ctrl->spl = output.spl_quiet;
200 pwr_ctrl->sppt = output.sppt_quiet;
201 pwr_ctrl->fppt = output.fppt_quiet;
202 pwr_ctrl->sppt_apu_only = output.sppt_apu_only_quiet;
203 pwr_ctrl->stt_min = output.stt_min_limit_quiet;
204 pwr_ctrl->stt_skin_temp[STT_TEMP_APU] = output.stt_apu_quiet;
205 pwr_ctrl->stt_skin_temp[STT_TEMP_HS2] = output.stt_hs2_quiet;
206
207 pwr_ctrl = &config_store.mode_set[AUTO_BALANCE].power_control;
208 pwr_ctrl->spl = output.spl_balanced;
209 pwr_ctrl->sppt = output.sppt_balanced;
210 pwr_ctrl->fppt = output.fppt_balanced;
211 pwr_ctrl->sppt_apu_only = output.sppt_apu_only_balanced;
212 pwr_ctrl->stt_min = output.stt_min_limit_balanced;
213 pwr_ctrl->stt_skin_temp[STT_TEMP_APU] = output.stt_apu_balanced;
214 pwr_ctrl->stt_skin_temp[STT_TEMP_HS2] = output.stt_hs2_balanced;
215
216 pwr_ctrl = &config_store.mode_set[AUTO_PERFORMANCE].power_control;
217 pwr_ctrl->spl = output.spl_perf;
218 pwr_ctrl->sppt = output.sppt_perf;
219 pwr_ctrl->fppt = output.fppt_perf;
220 pwr_ctrl->sppt_apu_only = output.sppt_apu_only_perf;
221 pwr_ctrl->stt_min = output.stt_min_limit_perf;
222 pwr_ctrl->stt_skin_temp[STT_TEMP_APU] = output.stt_apu_perf;
223 pwr_ctrl->stt_skin_temp[STT_TEMP_HS2] = output.stt_hs2_perf;
224
225 pwr_ctrl = &config_store.mode_set[AUTO_PERFORMANCE_ON_LAP].power_control;
226 pwr_ctrl->spl = output.spl_perf_on_lap;
227 pwr_ctrl->sppt = output.sppt_perf_on_lap;
228 pwr_ctrl->fppt = output.fppt_perf_on_lap;
229 pwr_ctrl->sppt_apu_only = output.sppt_apu_only_perf_on_lap;
230 pwr_ctrl->stt_min = output.stt_min_limit_perf_on_lap;
231 pwr_ctrl->stt_skin_temp[STT_TEMP_APU] = output.stt_apu_perf_on_lap;
232 pwr_ctrl->stt_skin_temp[STT_TEMP_HS2] = output.stt_hs2_perf_on_lap;
233
234 /* Fan ID */
235 config_store.mode_set[AUTO_QUIET].fan_control.fan_id = output.fan_id_quiet;
236 config_store.mode_set[AUTO_BALANCE].fan_control.fan_id = output.fan_id_balanced;
237 config_store.mode_set[AUTO_PERFORMANCE].fan_control.fan_id = output.fan_id_perf;
238 config_store.mode_set[AUTO_PERFORMANCE_ON_LAP].fan_control.fan_id =
239 output.fan_id_perf;
240
241 config_store.transition[AUTO_TRANSITION_TO_QUIET].target_mode = AUTO_QUIET;
242 config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].target_mode =
243 AUTO_PERFORMANCE;
244 config_store.transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].target_mode =
245 AUTO_BALANCE;
246 config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].target_mode =
247 AUTO_BALANCE;
248
249 config_store.transition[AUTO_TRANSITION_TO_QUIET].shifting_up = false;
250 config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].shifting_up = true;
251 config_store.transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].shifting_up = true;
252 config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].shifting_up =
253 false;
254
255 for (i = 0 ; i < AUTO_MODE_MAX ; i++) {
256 if (config_store.mode_set[i].fan_control.fan_id == FAN_INDEX_AUTO)
257 config_store.mode_set[i].fan_control.manual = false;
258 else
259 config_store.mode_set[i].fan_control.manual = true;
260 }
261
262 /* set to initial default values */
263 config_store.current_mode = AUTO_BALANCE;
264 dev->socket_power_history_idx = -1;
265}
266
267int amd_pmf_reset_amt(struct amd_pmf_dev *dev)
268{
269 /*
270 * OEM BIOS implementation guide says that if the auto mode is enabled
271 * the platform_profile registration shall be done by the OEM driver.
272 * There could be cases where both static slider and auto mode BIOS
273 * functions are enabled, in that case enable static slider updates
274 * only if it advertised as supported.
275 */
276
277 if (is_apmf_func_supported(dev, APMF_FUNC_STATIC_SLIDER_GRANULAR)) {
278 dev_dbg(dev->dev, "resetting AMT thermals\n");
279 amd_pmf_set_sps_power_limits(dev);
280 }
281 return 0;
282}
283
284void amd_pmf_handle_amt(struct amd_pmf_dev *dev)
285{
286 amd_pmf_set_automode(dev, config_store.current_mode, NULL);
287}
288
289void amd_pmf_deinit_auto_mode(struct amd_pmf_dev *dev)
290{
291 cancel_delayed_work_sync(&dev->work_buffer);
292}
293
294void amd_pmf_init_auto_mode(struct amd_pmf_dev *dev)
295{
296 amd_pmf_load_defaults_auto_mode(dev);
297 amd_pmf_init_metrics_table(dev);
298}
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}