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 #ifdef CONFIG_AMD_PMF_DEBUG 19 static 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 109 static void amd_pmf_dump_auto_mode_defaults(struct auto_mode_mode_config *data) {} 110 #endif 111 112 static 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 132 static 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 150 void 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 228 void 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 243 static 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 286 static 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 302 static 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 410 int 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 427 void amd_pmf_handle_amt(struct amd_pmf_dev *dev) 428 { 429 amd_pmf_set_automode(dev, config_store.current_mode, NULL); 430 } 431 432 void amd_pmf_deinit_auto_mode(struct amd_pmf_dev *dev) 433 { 434 cancel_delayed_work_sync(&dev->work_buffer); 435 } 436 437 void 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