1 // SPDX-License-Identifier: GPL-2.0
3 * AMD Platform Management Framework Driver
5 * Copyright (c) 2022, Advanced Micro Devices, Inc.
8 * Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
11 #include <linux/acpi.h>
12 #include <linux/workqueue.h>
15 static struct auto_mode_mode_config config_store;
16 static const char *state_as_str(unsigned int state);
18 static void amd_pmf_set_automode(struct amd_pmf_dev *dev, int idx,
19 struct auto_mode_mode_config *table)
21 struct power_table_control *pwr_ctrl = &config_store.mode_set[idx].power_control;
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);
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);
38 static int amd_pmf_get_moving_avg(struct amd_pmf_dev *pdev, int socket_power)
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;
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;
50 for (i = 0; i < AVG_SAMPLE_SIZE; i++)
51 total += pdev->socket_power_history[i];
53 return total / AVG_SAMPLE_SIZE;
56 void amd_pmf_trans_automode(struct amd_pmf_dev *dev, int socket_power, ktime_t time_elapsed_ms)
62 /* Get the average moving average computed by auto mode algorithm */
63 avg_power = amd_pmf_get_moving_avg(dev, socket_power);
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;
74 config_store.transition[i].timer = 0;
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;
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;
90 dev_dbg(dev->dev, "[AUTO_MODE] avg power: %u mW mode: %s\n", avg_power,
91 state_as_str(config_store.current_mode));
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);
111 void amd_pmf_update_2_cql(struct amd_pmf_dev *dev, bool is_cql_event)
113 int mode = config_store.current_mode;
115 config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].target_mode =
116 is_cql_event ? AUTO_PERFORMANCE_ON_LAP : AUTO_PERFORMANCE;
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);
123 dev_dbg(dev->dev, "updated CQL thermals\n");
126 static void amd_pmf_get_power_threshold(void)
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;
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;
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;
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;
145 static const char *state_as_str(unsigned int state)
152 case AUTO_PERFORMANCE_ON_LAP:
154 case AUTO_PERFORMANCE:
155 return "PERFORMANCE";
157 return "Unknown Auto Mode State";
161 static void amd_pmf_load_defaults_auto_mode(struct amd_pmf_dev *dev)
163 struct apmf_auto_mode output;
164 struct power_table_control *pwr_ctrl;
167 apmf_get_auto_mode_def(dev, &output);
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;
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;
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;
194 /* Power threshold */
195 amd_pmf_get_power_threshold();
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;
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;
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;
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;
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 =
241 config_store.transition[AUTO_TRANSITION_TO_QUIET].target_mode = AUTO_QUIET;
242 config_store.transition[AUTO_TRANSITION_TO_PERFORMANCE].target_mode =
244 config_store.transition[AUTO_TRANSITION_FROM_QUIET_TO_BALANCE].target_mode =
246 config_store.transition[AUTO_TRANSITION_FROM_PERFORMANCE_TO_BALANCE].target_mode =
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 =
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;
259 config_store.mode_set[i].fan_control.manual = true;
262 /* set to initial default values */
263 config_store.current_mode = AUTO_BALANCE;
264 dev->socket_power_history_idx = -1;
267 int amd_pmf_reset_amt(struct amd_pmf_dev *dev)
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.
277 if (is_apmf_func_supported(dev, APMF_FUNC_STATIC_SLIDER_GRANULAR)) {
278 int mode = amd_pmf_get_pprof_modes(dev);
283 dev_dbg(dev->dev, "resetting AMT thermals\n");
284 amd_pmf_update_slider(dev, SLIDER_OP_SET, mode, NULL);
289 void amd_pmf_handle_amt(struct amd_pmf_dev *dev)
291 amd_pmf_set_automode(dev, config_store.current_mode, NULL);
294 void amd_pmf_deinit_auto_mode(struct amd_pmf_dev *dev)
296 cancel_delayed_work_sync(&dev->work_buffer);
299 void amd_pmf_init_auto_mode(struct amd_pmf_dev *dev)
301 amd_pmf_load_defaults_auto_mode(dev);
302 /* update the thermal limits for Automode */
303 amd_pmf_set_automode(dev, config_store.current_mode, NULL);
304 amd_pmf_init_metrics_table(dev);