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 } 299