429 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * AMD Platform Management Framework (PMF) Driver4 *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 "pmf.h"12 13static struct amd_pmf_static_slider_granular_v2 config_store_v2;14static struct amd_pmf_static_slider_granular config_store;15static struct amd_pmf_apts_granular apts_config_store;16 17#ifdef CONFIG_AMD_PMF_DEBUG18static const char *slider_v2_as_str(unsigned int state)19{20 switch (state) {21 case POWER_MODE_BEST_PERFORMANCE:22 return "Best Performance";23 case POWER_MODE_BALANCED:24 return "Balanced";25 case POWER_MODE_BEST_POWER_EFFICIENCY:26 return "Best Power Efficiency";27 case POWER_MODE_ENERGY_SAVE:28 return "Energy Save";29 default:30 return "Unknown Power Mode";31 }32}33 34static const char *slider_as_str(unsigned int state)35{36 switch (state) {37 case POWER_MODE_PERFORMANCE:38 return "PERFORMANCE";39 case POWER_MODE_BALANCED_POWER:40 return "BALANCED_POWER";41 case POWER_MODE_POWER_SAVER:42 return "POWER_SAVER";43 default:44 return "Unknown Slider State";45 }46}47 48const char *amd_pmf_source_as_str(unsigned int state)49{50 switch (state) {51 case POWER_SOURCE_AC:52 return "AC";53 case POWER_SOURCE_DC:54 return "DC";55 default:56 return "Unknown Power State";57 }58}59 60static void amd_pmf_dump_sps_defaults(struct amd_pmf_static_slider_granular *data)61{62 int i, j;63 64 pr_debug("Static Slider Data - BEGIN\n");65 66 for (i = 0; i < POWER_SOURCE_MAX; i++) {67 for (j = 0; j < POWER_MODE_MAX; j++) {68 pr_debug("--- Source:%s Mode:%s ---\n", amd_pmf_source_as_str(i),69 slider_as_str(j));70 pr_debug("SPL: %u mW\n", data->prop[i][j].spl);71 pr_debug("SPPT: %u mW\n", data->prop[i][j].sppt);72 pr_debug("SPPT_ApuOnly: %u mW\n", data->prop[i][j].sppt_apu_only);73 pr_debug("FPPT: %u mW\n", data->prop[i][j].fppt);74 pr_debug("STTMinLimit: %u mW\n", data->prop[i][j].stt_min);75 pr_debug("STT_SkinTempLimit_APU: %u C\n",76 data->prop[i][j].stt_skin_temp[STT_TEMP_APU]);77 pr_debug("STT_SkinTempLimit_HS2: %u C\n",78 data->prop[i][j].stt_skin_temp[STT_TEMP_HS2]);79 }80 }81 82 pr_debug("Static Slider Data - END\n");83}84 85static void amd_pmf_dump_sps_defaults_v2(struct amd_pmf_static_slider_granular_v2 *data)86{87 unsigned int i, j;88 89 pr_debug("Static Slider APTS state index data - BEGIN");90 pr_debug("size: %u\n", data->size);91 92 for (i = 0; i < POWER_SOURCE_MAX; i++)93 for (j = 0; j < POWER_MODE_V2_MAX; j++)94 pr_debug("%s %s: %u\n", amd_pmf_source_as_str(i), slider_v2_as_str(j),95 data->sps_idx.power_states[i][j]);96 97 pr_debug("Static Slider APTS state index data - END\n");98}99 100static void amd_pmf_dump_apts_sps_defaults(struct amd_pmf_apts_granular *info)101{102 int i;103 104 pr_debug("Static Slider APTS index default values data - BEGIN");105 106 for (i = 0; i < APTS_MAX_STATES; i++) {107 pr_debug("Table Version[%d] = %u\n", i, info->val[i].table_version);108 pr_debug("Fan Index[%d] = %u\n", i, info->val[i].fan_table_idx);109 pr_debug("PPT[%d] = %u\n", i, info->val[i].pmf_ppt);110 pr_debug("PPT APU[%d] = %u\n", i, info->val[i].ppt_pmf_apu_only);111 pr_debug("STT Min[%d] = %u\n", i, info->val[i].stt_min_limit);112 pr_debug("STT APU[%d] = %u\n", i, info->val[i].stt_skin_temp_limit_apu);113 pr_debug("STT HS2[%d] = %u\n", i, info->val[i].stt_skin_temp_limit_hs2);114 }115 116 pr_debug("Static Slider APTS index default values data - END");117}118#else119static void amd_pmf_dump_sps_defaults(struct amd_pmf_static_slider_granular *data) {}120static void amd_pmf_dump_sps_defaults_v2(struct amd_pmf_static_slider_granular_v2 *data) {}121static void amd_pmf_dump_apts_sps_defaults(struct amd_pmf_apts_granular *info) {}122#endif123 124static void amd_pmf_load_apts_defaults_sps_v2(struct amd_pmf_dev *pdev)125{126 struct amd_pmf_apts_granular_output output;127 struct amd_pmf_apts_output *ps;128 int i;129 130 memset(&apts_config_store, 0, sizeof(apts_config_store));131 132 ps = apts_config_store.val;133 134 for (i = 0; i < APTS_MAX_STATES; i++) {135 apts_get_static_slider_granular_v2(pdev, &output, i);136 ps[i].table_version = output.val.table_version;137 ps[i].fan_table_idx = output.val.fan_table_idx;138 ps[i].pmf_ppt = output.val.pmf_ppt;139 ps[i].ppt_pmf_apu_only = output.val.ppt_pmf_apu_only;140 ps[i].stt_min_limit = output.val.stt_min_limit;141 ps[i].stt_skin_temp_limit_apu = output.val.stt_skin_temp_limit_apu;142 ps[i].stt_skin_temp_limit_hs2 = output.val.stt_skin_temp_limit_hs2;143 }144 145 amd_pmf_dump_apts_sps_defaults(&apts_config_store);146}147 148static void amd_pmf_load_defaults_sps_v2(struct amd_pmf_dev *dev)149{150 struct apmf_static_slider_granular_output_v2 output;151 unsigned int i, j;152 153 memset(&config_store_v2, 0, sizeof(config_store_v2));154 apmf_get_static_slider_granular_v2(dev, &output);155 156 config_store_v2.size = output.size;157 158 for (i = 0; i < POWER_SOURCE_MAX; i++)159 for (j = 0; j < POWER_MODE_V2_MAX; j++)160 config_store_v2.sps_idx.power_states[i][j] =161 output.sps_idx.power_states[i][j];162 163 amd_pmf_dump_sps_defaults_v2(&config_store_v2);164}165 166static void amd_pmf_load_defaults_sps(struct amd_pmf_dev *dev)167{168 struct apmf_static_slider_granular_output output;169 int i, j, idx = 0;170 171 memset(&config_store, 0, sizeof(config_store));172 apmf_get_static_slider_granular(dev, &output);173 174 for (i = 0; i < POWER_SOURCE_MAX; i++) {175 for (j = 0; j < POWER_MODE_MAX; j++) {176 config_store.prop[i][j].spl = output.prop[idx].spl;177 config_store.prop[i][j].sppt = output.prop[idx].sppt;178 config_store.prop[i][j].sppt_apu_only =179 output.prop[idx].sppt_apu_only;180 config_store.prop[i][j].fppt = output.prop[idx].fppt;181 config_store.prop[i][j].stt_min = output.prop[idx].stt_min;182 config_store.prop[i][j].stt_skin_temp[STT_TEMP_APU] =183 output.prop[idx].stt_skin_temp[STT_TEMP_APU];184 config_store.prop[i][j].stt_skin_temp[STT_TEMP_HS2] =185 output.prop[idx].stt_skin_temp[STT_TEMP_HS2];186 config_store.prop[i][j].fan_id = output.prop[idx].fan_id;187 idx++;188 }189 }190 amd_pmf_dump_sps_defaults(&config_store);191}192 193static void amd_pmf_update_slider_v2(struct amd_pmf_dev *dev, int idx)194{195 amd_pmf_send_cmd(dev, SET_PMF_PPT, false, apts_config_store.val[idx].pmf_ppt, NULL);196 amd_pmf_send_cmd(dev, SET_PMF_PPT_APU_ONLY, false,197 apts_config_store.val[idx].ppt_pmf_apu_only, NULL);198 amd_pmf_send_cmd(dev, SET_STT_MIN_LIMIT, false,199 apts_config_store.val[idx].stt_min_limit, NULL);200 amd_pmf_send_cmd(dev, SET_STT_LIMIT_APU, false,201 apts_config_store.val[idx].stt_skin_temp_limit_apu, NULL);202 amd_pmf_send_cmd(dev, SET_STT_LIMIT_HS2, false,203 apts_config_store.val[idx].stt_skin_temp_limit_hs2, NULL);204}205 206void amd_pmf_update_slider(struct amd_pmf_dev *dev, bool op, int idx,207 struct amd_pmf_static_slider_granular *table)208{209 int src = amd_pmf_get_power_source();210 211 if (op == SLIDER_OP_SET) {212 amd_pmf_send_cmd(dev, SET_SPL, false, config_store.prop[src][idx].spl, NULL);213 amd_pmf_send_cmd(dev, SET_FPPT, false, config_store.prop[src][idx].fppt, NULL);214 amd_pmf_send_cmd(dev, SET_SPPT, false, config_store.prop[src][idx].sppt, NULL);215 amd_pmf_send_cmd(dev, SET_SPPT_APU_ONLY, false,216 config_store.prop[src][idx].sppt_apu_only, NULL);217 amd_pmf_send_cmd(dev, SET_STT_MIN_LIMIT, false,218 config_store.prop[src][idx].stt_min, NULL);219 amd_pmf_send_cmd(dev, SET_STT_LIMIT_APU, false,220 config_store.prop[src][idx].stt_skin_temp[STT_TEMP_APU], NULL);221 amd_pmf_send_cmd(dev, SET_STT_LIMIT_HS2, false,222 config_store.prop[src][idx].stt_skin_temp[STT_TEMP_HS2], NULL);223 } else if (op == SLIDER_OP_GET) {224 amd_pmf_send_cmd(dev, GET_SPL, true, ARG_NONE, &table->prop[src][idx].spl);225 amd_pmf_send_cmd(dev, GET_FPPT, true, ARG_NONE, &table->prop[src][idx].fppt);226 amd_pmf_send_cmd(dev, GET_SPPT, true, ARG_NONE, &table->prop[src][idx].sppt);227 amd_pmf_send_cmd(dev, GET_SPPT_APU_ONLY, true, ARG_NONE,228 &table->prop[src][idx].sppt_apu_only);229 amd_pmf_send_cmd(dev, GET_STT_MIN_LIMIT, true, ARG_NONE,230 &table->prop[src][idx].stt_min);231 amd_pmf_send_cmd(dev, GET_STT_LIMIT_APU, true, ARG_NONE,232 (u32 *)&table->prop[src][idx].stt_skin_temp[STT_TEMP_APU]);233 amd_pmf_send_cmd(dev, GET_STT_LIMIT_HS2, true, ARG_NONE,234 (u32 *)&table->prop[src][idx].stt_skin_temp[STT_TEMP_HS2]);235 }236}237 238static int amd_pmf_update_sps_power_limits_v2(struct amd_pmf_dev *pdev, int pwr_mode)239{240 int src, index;241 242 src = amd_pmf_get_power_source();243 244 switch (pwr_mode) {245 case POWER_MODE_PERFORMANCE:246 index = config_store_v2.sps_idx.power_states[src][POWER_MODE_BEST_PERFORMANCE];247 amd_pmf_update_slider_v2(pdev, index);248 break;249 case POWER_MODE_BALANCED_POWER:250 index = config_store_v2.sps_idx.power_states[src][POWER_MODE_BALANCED];251 amd_pmf_update_slider_v2(pdev, index);252 break;253 case POWER_MODE_POWER_SAVER:254 index = config_store_v2.sps_idx.power_states[src][POWER_MODE_BEST_POWER_EFFICIENCY];255 amd_pmf_update_slider_v2(pdev, index);256 break;257 default:258 return -EINVAL;259 }260 261 return 0;262}263 264int amd_pmf_set_sps_power_limits(struct amd_pmf_dev *pmf)265{266 int mode;267 268 mode = amd_pmf_get_pprof_modes(pmf);269 if (mode < 0)270 return mode;271 272 if (pmf->pmf_if_version == PMF_IF_V2)273 return amd_pmf_update_sps_power_limits_v2(pmf, mode);274 275 amd_pmf_update_slider(pmf, SLIDER_OP_SET, mode, NULL);276 277 return 0;278}279 280bool is_pprof_balanced(struct amd_pmf_dev *pmf)281{282 return (pmf->current_profile == PLATFORM_PROFILE_BALANCED) ? true : false;283}284 285static int amd_pmf_profile_get(struct platform_profile_handler *pprof,286 enum platform_profile_option *profile)287{288 struct amd_pmf_dev *pmf = container_of(pprof, struct amd_pmf_dev, pprof);289 290 *profile = pmf->current_profile;291 return 0;292}293 294int amd_pmf_get_pprof_modes(struct amd_pmf_dev *pmf)295{296 int mode;297 298 switch (pmf->current_profile) {299 case PLATFORM_PROFILE_PERFORMANCE:300 mode = POWER_MODE_PERFORMANCE;301 break;302 case PLATFORM_PROFILE_BALANCED:303 mode = POWER_MODE_BALANCED_POWER;304 break;305 case PLATFORM_PROFILE_LOW_POWER:306 mode = POWER_MODE_POWER_SAVER;307 break;308 default:309 dev_err(pmf->dev, "Unknown Platform Profile.\n");310 return -EOPNOTSUPP;311 }312 313 return mode;314}315 316int amd_pmf_power_slider_update_event(struct amd_pmf_dev *dev)317{318 u8 flag = 0;319 int mode;320 int src;321 322 mode = amd_pmf_get_pprof_modes(dev);323 if (mode < 0)324 return mode;325 326 src = amd_pmf_get_power_source();327 328 if (src == POWER_SOURCE_AC) {329 switch (mode) {330 case POWER_MODE_PERFORMANCE:331 flag |= BIT(AC_BEST_PERF);332 break;333 case POWER_MODE_BALANCED_POWER:334 flag |= BIT(AC_BETTER_PERF);335 break;336 case POWER_MODE_POWER_SAVER:337 flag |= BIT(AC_BETTER_BATTERY);338 break;339 default:340 dev_err(dev->dev, "unsupported platform profile\n");341 return -EOPNOTSUPP;342 }343 344 } else if (src == POWER_SOURCE_DC) {345 switch (mode) {346 case POWER_MODE_PERFORMANCE:347 flag |= BIT(DC_BEST_PERF);348 break;349 case POWER_MODE_BALANCED_POWER:350 flag |= BIT(DC_BETTER_PERF);351 break;352 case POWER_MODE_POWER_SAVER:353 flag |= BIT(DC_BATTERY_SAVER);354 break;355 default:356 dev_err(dev->dev, "unsupported platform profile\n");357 return -EOPNOTSUPP;358 }359 }360 361 apmf_os_power_slider_update(dev, flag);362 363 return 0;364}365 366static int amd_pmf_profile_set(struct platform_profile_handler *pprof,367 enum platform_profile_option profile)368{369 struct amd_pmf_dev *pmf = container_of(pprof, struct amd_pmf_dev, pprof);370 int ret = 0;371 372 pmf->current_profile = profile;373 374 /* Notify EC about the slider position change */375 if (is_apmf_func_supported(pmf, APMF_FUNC_OS_POWER_SLIDER_UPDATE)) {376 ret = amd_pmf_power_slider_update_event(pmf);377 if (ret)378 return ret;379 }380 381 if (is_apmf_func_supported(pmf, APMF_FUNC_STATIC_SLIDER_GRANULAR)) {382 ret = amd_pmf_set_sps_power_limits(pmf);383 if (ret)384 return ret;385 }386 387 return 0;388}389 390int amd_pmf_init_sps(struct amd_pmf_dev *dev)391{392 int err;393 394 dev->current_profile = PLATFORM_PROFILE_BALANCED;395 396 if (is_apmf_func_supported(dev, APMF_FUNC_STATIC_SLIDER_GRANULAR)) {397 if (dev->pmf_if_version == PMF_IF_V2) {398 amd_pmf_load_defaults_sps_v2(dev);399 amd_pmf_load_apts_defaults_sps_v2(dev);400 } else {401 amd_pmf_load_defaults_sps(dev);402 }403 404 /* update SPS balanced power mode thermals */405 amd_pmf_set_sps_power_limits(dev);406 }407 408 dev->pprof.profile_get = amd_pmf_profile_get;409 dev->pprof.profile_set = amd_pmf_profile_set;410 411 /* Setup supported modes */412 set_bit(PLATFORM_PROFILE_LOW_POWER, dev->pprof.choices);413 set_bit(PLATFORM_PROFILE_BALANCED, dev->pprof.choices);414 set_bit(PLATFORM_PROFILE_PERFORMANCE, dev->pprof.choices);415 416 /* Create platform_profile structure and register */417 err = platform_profile_register(&dev->pprof);418 if (err)419 dev_err(dev->dev, "Failed to register SPS support, this is most likely an SBIOS bug: %d\n",420 err);421 422 return err;423}424 425void amd_pmf_deinit_sps(struct amd_pmf_dev *dev)426{427 platform_profile_remove();428}429