Merge tag 'block-6.2-2023-02-03' of git://git.kernel.dk/linux
[linux-2.6-microblaze.git] / drivers / platform / x86 / amd / pmf / auto-mode.c
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
15 static struct auto_mode_mode_config config_store;
16 static const char *state_as_str(unsigned int state);
17
18 static 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
38 static 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
56 void 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
111 void 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
126 static 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
145 static 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
161 static 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
267 int 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
284 void amd_pmf_handle_amt(struct amd_pmf_dev *dev)
285 {
286         amd_pmf_set_automode(dev, config_store.current_mode, NULL);
287 }
288
289 void amd_pmf_deinit_auto_mode(struct amd_pmf_dev *dev)
290 {
291         cancel_delayed_work_sync(&dev->work_buffer);
292 }
293
294 void 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 }