| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432 |
- // SPDX-License-Identifier: GPL-2.0
- /*
- * AMD Platform Management Framework (PMF) Driver
- *
- * Copyright (c) 2022, Advanced Micro Devices, Inc.
- * All Rights Reserved.
- *
- * Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
- */
- #include "pmf.h"
- static struct amd_pmf_static_slider_granular_v2 config_store_v2;
- static struct amd_pmf_static_slider_granular config_store;
- static struct amd_pmf_apts_granular apts_config_store;
- #ifdef CONFIG_AMD_PMF_DEBUG
- static const char *slider_v2_as_str(unsigned int state)
- {
- switch (state) {
- case POWER_MODE_BEST_PERFORMANCE:
- return "Best Performance";
- case POWER_MODE_BALANCED:
- return "Balanced";
- case POWER_MODE_BEST_POWER_EFFICIENCY:
- return "Best Power Efficiency";
- case POWER_MODE_ENERGY_SAVE:
- return "Energy Save";
- default:
- return "Unknown Power Mode";
- }
- }
- static const char *slider_as_str(unsigned int state)
- {
- switch (state) {
- case POWER_MODE_PERFORMANCE:
- return "PERFORMANCE";
- case POWER_MODE_BALANCED_POWER:
- return "BALANCED_POWER";
- case POWER_MODE_POWER_SAVER:
- return "POWER_SAVER";
- default:
- return "Unknown Slider State";
- }
- }
- const char *amd_pmf_source_as_str(unsigned int state)
- {
- switch (state) {
- case POWER_SOURCE_AC:
- return "AC";
- case POWER_SOURCE_DC:
- return "DC";
- default:
- return "Unknown Power State";
- }
- }
- static void amd_pmf_dump_sps_defaults(struct amd_pmf_static_slider_granular *data)
- {
- int i, j;
- pr_debug("Static Slider Data - BEGIN\n");
- for (i = 0; i < POWER_SOURCE_MAX; i++) {
- for (j = 0; j < POWER_MODE_MAX; j++) {
- pr_debug("--- Source:%s Mode:%s ---\n", amd_pmf_source_as_str(i),
- slider_as_str(j));
- pr_debug("SPL: %u mW\n", data->prop[i][j].spl);
- pr_debug("SPPT: %u mW\n", data->prop[i][j].sppt);
- pr_debug("SPPT_ApuOnly: %u mW\n", data->prop[i][j].sppt_apu_only);
- pr_debug("FPPT: %u mW\n", data->prop[i][j].fppt);
- pr_debug("STTMinLimit: %u mW\n", data->prop[i][j].stt_min);
- pr_debug("STT_SkinTempLimit_APU: %u C\n",
- data->prop[i][j].stt_skin_temp[STT_TEMP_APU]);
- pr_debug("STT_SkinTempLimit_HS2: %u C\n",
- data->prop[i][j].stt_skin_temp[STT_TEMP_HS2]);
- }
- }
- pr_debug("Static Slider Data - END\n");
- }
- static void amd_pmf_dump_sps_defaults_v2(struct amd_pmf_static_slider_granular_v2 *data)
- {
- unsigned int i, j;
- pr_debug("Static Slider APTS state index data - BEGIN");
- pr_debug("size: %u\n", data->size);
- for (i = 0; i < POWER_SOURCE_MAX; i++)
- for (j = 0; j < POWER_MODE_V2_MAX; j++)
- pr_debug("%s %s: %u\n", amd_pmf_source_as_str(i), slider_v2_as_str(j),
- data->sps_idx.power_states[i][j]);
- pr_debug("Static Slider APTS state index data - END\n");
- }
- static void amd_pmf_dump_apts_sps_defaults(struct amd_pmf_apts_granular *info)
- {
- int i;
- pr_debug("Static Slider APTS index default values data - BEGIN");
- for (i = 0; i < APTS_MAX_STATES; i++) {
- pr_debug("Table Version[%d] = %u\n", i, info->val[i].table_version);
- pr_debug("Fan Index[%d] = %u\n", i, info->val[i].fan_table_idx);
- pr_debug("PPT[%d] = %u\n", i, info->val[i].pmf_ppt);
- pr_debug("PPT APU[%d] = %u\n", i, info->val[i].ppt_pmf_apu_only);
- pr_debug("STT Min[%d] = %u\n", i, info->val[i].stt_min_limit);
- pr_debug("STT APU[%d] = %u\n", i, info->val[i].stt_skin_temp_limit_apu);
- pr_debug("STT HS2[%d] = %u\n", i, info->val[i].stt_skin_temp_limit_hs2);
- }
- pr_debug("Static Slider APTS index default values data - END");
- }
- #else
- static void amd_pmf_dump_sps_defaults(struct amd_pmf_static_slider_granular *data) {}
- static void amd_pmf_dump_sps_defaults_v2(struct amd_pmf_static_slider_granular_v2 *data) {}
- static void amd_pmf_dump_apts_sps_defaults(struct amd_pmf_apts_granular *info) {}
- #endif
- static void amd_pmf_load_apts_defaults_sps_v2(struct amd_pmf_dev *pdev)
- {
- struct amd_pmf_apts_granular_output output;
- struct amd_pmf_apts_output *ps;
- int i;
- memset(&apts_config_store, 0, sizeof(apts_config_store));
- ps = apts_config_store.val;
- for (i = 0; i < APTS_MAX_STATES; i++) {
- apts_get_static_slider_granular_v2(pdev, &output, i);
- ps[i].table_version = output.val.table_version;
- ps[i].fan_table_idx = output.val.fan_table_idx;
- ps[i].pmf_ppt = output.val.pmf_ppt;
- ps[i].ppt_pmf_apu_only = output.val.ppt_pmf_apu_only;
- ps[i].stt_min_limit = output.val.stt_min_limit;
- ps[i].stt_skin_temp_limit_apu = output.val.stt_skin_temp_limit_apu;
- ps[i].stt_skin_temp_limit_hs2 = output.val.stt_skin_temp_limit_hs2;
- }
- amd_pmf_dump_apts_sps_defaults(&apts_config_store);
- }
- static void amd_pmf_load_defaults_sps_v2(struct amd_pmf_dev *dev)
- {
- struct apmf_static_slider_granular_output_v2 output;
- unsigned int i, j;
- memset(&config_store_v2, 0, sizeof(config_store_v2));
- apmf_get_static_slider_granular_v2(dev, &output);
- config_store_v2.size = output.size;
- for (i = 0; i < POWER_SOURCE_MAX; i++)
- for (j = 0; j < POWER_MODE_V2_MAX; j++)
- config_store_v2.sps_idx.power_states[i][j] =
- output.sps_idx.power_states[i][j];
- amd_pmf_dump_sps_defaults_v2(&config_store_v2);
- }
- static void amd_pmf_load_defaults_sps(struct amd_pmf_dev *dev)
- {
- struct apmf_static_slider_granular_output output;
- int i, j, idx = 0;
- memset(&config_store, 0, sizeof(config_store));
- apmf_get_static_slider_granular(dev, &output);
- for (i = 0; i < POWER_SOURCE_MAX; i++) {
- for (j = 0; j < POWER_MODE_MAX; j++) {
- config_store.prop[i][j].spl = output.prop[idx].spl;
- config_store.prop[i][j].sppt = output.prop[idx].sppt;
- config_store.prop[i][j].sppt_apu_only =
- output.prop[idx].sppt_apu_only;
- config_store.prop[i][j].fppt = output.prop[idx].fppt;
- config_store.prop[i][j].stt_min = output.prop[idx].stt_min;
- config_store.prop[i][j].stt_skin_temp[STT_TEMP_APU] =
- output.prop[idx].stt_skin_temp[STT_TEMP_APU];
- config_store.prop[i][j].stt_skin_temp[STT_TEMP_HS2] =
- output.prop[idx].stt_skin_temp[STT_TEMP_HS2];
- config_store.prop[i][j].fan_id = output.prop[idx].fan_id;
- idx++;
- }
- }
- amd_pmf_dump_sps_defaults(&config_store);
- }
- static void amd_pmf_update_slider_v2(struct amd_pmf_dev *dev, int idx)
- {
- amd_pmf_send_cmd(dev, SET_PMF_PPT, false, apts_config_store.val[idx].pmf_ppt, NULL);
- amd_pmf_send_cmd(dev, SET_PMF_PPT_APU_ONLY, false,
- apts_config_store.val[idx].ppt_pmf_apu_only, NULL);
- amd_pmf_send_cmd(dev, SET_STT_MIN_LIMIT, false,
- apts_config_store.val[idx].stt_min_limit, NULL);
- amd_pmf_send_cmd(dev, SET_STT_LIMIT_APU, false,
- fixp_q88_fromint(apts_config_store.val[idx].stt_skin_temp_limit_apu),
- NULL);
- amd_pmf_send_cmd(dev, SET_STT_LIMIT_HS2, false,
- fixp_q88_fromint(apts_config_store.val[idx].stt_skin_temp_limit_hs2),
- NULL);
- }
- void amd_pmf_update_slider(struct amd_pmf_dev *dev, bool op, int idx,
- struct amd_pmf_static_slider_granular *table)
- {
- int src = amd_pmf_get_power_source();
- if (op == SLIDER_OP_SET) {
- amd_pmf_send_cmd(dev, SET_SPL, false, config_store.prop[src][idx].spl, NULL);
- amd_pmf_send_cmd(dev, SET_FPPT, false, config_store.prop[src][idx].fppt, NULL);
- amd_pmf_send_cmd(dev, SET_SPPT, false, config_store.prop[src][idx].sppt, NULL);
- amd_pmf_send_cmd(dev, SET_SPPT_APU_ONLY, false,
- config_store.prop[src][idx].sppt_apu_only, NULL);
- amd_pmf_send_cmd(dev, SET_STT_MIN_LIMIT, false,
- config_store.prop[src][idx].stt_min, NULL);
- amd_pmf_send_cmd(dev, SET_STT_LIMIT_APU, false,
- fixp_q88_fromint(config_store.prop[src][idx].stt_skin_temp[STT_TEMP_APU]),
- NULL);
- amd_pmf_send_cmd(dev, SET_STT_LIMIT_HS2, false,
- fixp_q88_fromint(config_store.prop[src][idx].stt_skin_temp[STT_TEMP_HS2]),
- NULL);
- } else if (op == SLIDER_OP_GET) {
- amd_pmf_send_cmd(dev, GET_SPL, true, ARG_NONE, &table->prop[src][idx].spl);
- amd_pmf_send_cmd(dev, GET_FPPT, true, ARG_NONE, &table->prop[src][idx].fppt);
- amd_pmf_send_cmd(dev, GET_SPPT, true, ARG_NONE, &table->prop[src][idx].sppt);
- amd_pmf_send_cmd(dev, GET_SPPT_APU_ONLY, true, ARG_NONE,
- &table->prop[src][idx].sppt_apu_only);
- amd_pmf_send_cmd(dev, GET_STT_MIN_LIMIT, true, ARG_NONE,
- &table->prop[src][idx].stt_min);
- amd_pmf_send_cmd(dev, GET_STT_LIMIT_APU, true, ARG_NONE,
- (u32 *)&table->prop[src][idx].stt_skin_temp[STT_TEMP_APU]);
- amd_pmf_send_cmd(dev, GET_STT_LIMIT_HS2, true, ARG_NONE,
- (u32 *)&table->prop[src][idx].stt_skin_temp[STT_TEMP_HS2]);
- }
- }
- static int amd_pmf_update_sps_power_limits_v2(struct amd_pmf_dev *pdev, int pwr_mode)
- {
- int src, index;
- src = amd_pmf_get_power_source();
- switch (pwr_mode) {
- case POWER_MODE_PERFORMANCE:
- index = config_store_v2.sps_idx.power_states[src][POWER_MODE_BEST_PERFORMANCE];
- amd_pmf_update_slider_v2(pdev, index);
- break;
- case POWER_MODE_BALANCED_POWER:
- index = config_store_v2.sps_idx.power_states[src][POWER_MODE_BALANCED];
- amd_pmf_update_slider_v2(pdev, index);
- break;
- case POWER_MODE_POWER_SAVER:
- index = config_store_v2.sps_idx.power_states[src][POWER_MODE_BEST_POWER_EFFICIENCY];
- amd_pmf_update_slider_v2(pdev, index);
- break;
- default:
- return -EINVAL;
- }
- return 0;
- }
- int amd_pmf_set_sps_power_limits(struct amd_pmf_dev *pmf)
- {
- int mode;
- mode = amd_pmf_get_pprof_modes(pmf);
- if (mode < 0)
- return mode;
- if (pmf->pmf_if_version == PMF_IF_V2)
- return amd_pmf_update_sps_power_limits_v2(pmf, mode);
- amd_pmf_update_slider(pmf, SLIDER_OP_SET, mode, NULL);
- return 0;
- }
- bool is_pprof_balanced(struct amd_pmf_dev *pmf)
- {
- return (pmf->current_profile == PLATFORM_PROFILE_BALANCED) ? true : false;
- }
- static int amd_pmf_profile_get(struct platform_profile_handler *pprof,
- enum platform_profile_option *profile)
- {
- struct amd_pmf_dev *pmf = container_of(pprof, struct amd_pmf_dev, pprof);
- *profile = pmf->current_profile;
- return 0;
- }
- int amd_pmf_get_pprof_modes(struct amd_pmf_dev *pmf)
- {
- int mode;
- switch (pmf->current_profile) {
- case PLATFORM_PROFILE_PERFORMANCE:
- mode = POWER_MODE_PERFORMANCE;
- break;
- case PLATFORM_PROFILE_BALANCED:
- mode = POWER_MODE_BALANCED_POWER;
- break;
- case PLATFORM_PROFILE_LOW_POWER:
- mode = POWER_MODE_POWER_SAVER;
- break;
- default:
- dev_err(pmf->dev, "Unknown Platform Profile.\n");
- return -EOPNOTSUPP;
- }
- return mode;
- }
- int amd_pmf_power_slider_update_event(struct amd_pmf_dev *dev)
- {
- u8 flag = 0;
- int mode;
- int src;
- mode = amd_pmf_get_pprof_modes(dev);
- if (mode < 0)
- return mode;
- src = amd_pmf_get_power_source();
- if (src == POWER_SOURCE_AC) {
- switch (mode) {
- case POWER_MODE_PERFORMANCE:
- flag |= BIT(AC_BEST_PERF);
- break;
- case POWER_MODE_BALANCED_POWER:
- flag |= BIT(AC_BETTER_PERF);
- break;
- case POWER_MODE_POWER_SAVER:
- flag |= BIT(AC_BETTER_BATTERY);
- break;
- default:
- dev_err(dev->dev, "unsupported platform profile\n");
- return -EOPNOTSUPP;
- }
- } else if (src == POWER_SOURCE_DC) {
- switch (mode) {
- case POWER_MODE_PERFORMANCE:
- flag |= BIT(DC_BEST_PERF);
- break;
- case POWER_MODE_BALANCED_POWER:
- flag |= BIT(DC_BETTER_PERF);
- break;
- case POWER_MODE_POWER_SAVER:
- flag |= BIT(DC_BATTERY_SAVER);
- break;
- default:
- dev_err(dev->dev, "unsupported platform profile\n");
- return -EOPNOTSUPP;
- }
- }
- apmf_os_power_slider_update(dev, flag);
- return 0;
- }
- static int amd_pmf_profile_set(struct platform_profile_handler *pprof,
- enum platform_profile_option profile)
- {
- struct amd_pmf_dev *pmf = container_of(pprof, struct amd_pmf_dev, pprof);
- int ret = 0;
- pmf->current_profile = profile;
- /* Notify EC about the slider position change */
- if (is_apmf_func_supported(pmf, APMF_FUNC_OS_POWER_SLIDER_UPDATE)) {
- ret = amd_pmf_power_slider_update_event(pmf);
- if (ret)
- return ret;
- }
- if (is_apmf_func_supported(pmf, APMF_FUNC_STATIC_SLIDER_GRANULAR)) {
- ret = amd_pmf_set_sps_power_limits(pmf);
- if (ret)
- return ret;
- }
- return 0;
- }
- int amd_pmf_init_sps(struct amd_pmf_dev *dev)
- {
- int err;
- dev->current_profile = PLATFORM_PROFILE_BALANCED;
- if (is_apmf_func_supported(dev, APMF_FUNC_STATIC_SLIDER_GRANULAR)) {
- if (dev->pmf_if_version == PMF_IF_V2) {
- amd_pmf_load_defaults_sps_v2(dev);
- amd_pmf_load_apts_defaults_sps_v2(dev);
- } else {
- amd_pmf_load_defaults_sps(dev);
- }
- /* update SPS balanced power mode thermals */
- amd_pmf_set_sps_power_limits(dev);
- }
- dev->pprof.profile_get = amd_pmf_profile_get;
- dev->pprof.profile_set = amd_pmf_profile_set;
- /* Setup supported modes */
- set_bit(PLATFORM_PROFILE_LOW_POWER, dev->pprof.choices);
- set_bit(PLATFORM_PROFILE_BALANCED, dev->pprof.choices);
- set_bit(PLATFORM_PROFILE_PERFORMANCE, dev->pprof.choices);
- /* Create platform_profile structure and register */
- err = platform_profile_register(&dev->pprof);
- if (err)
- dev_err(dev->dev, "Failed to register SPS support, this is most likely an SBIOS bug: %d\n",
- err);
- return err;
- }
- void amd_pmf_deinit_sps(struct amd_pmf_dev *dev)
- {
- platform_profile_remove();
- }
|