14c71ae41SShyam Sundar S K // SPDX-License-Identifier: GPL-2.0 24c71ae41SShyam Sundar S K /* 34c71ae41SShyam Sundar S K * AMD Platform Management Framework (PMF) Driver 44c71ae41SShyam Sundar S K * 54c71ae41SShyam Sundar S K * Copyright (c) 2022, Advanced Micro Devices, Inc. 64c71ae41SShyam Sundar S K * All Rights Reserved. 74c71ae41SShyam Sundar S K * 84c71ae41SShyam Sundar S K * Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com> 94c71ae41SShyam Sundar S K */ 104c71ae41SShyam Sundar S K 114c71ae41SShyam Sundar S K #include "pmf.h" 124c71ae41SShyam Sundar S K 134c71ae41SShyam Sundar S K static struct amd_pmf_static_slider_granular config_store; 144c71ae41SShyam Sundar S K 15a82ebb3dSShyam Sundar S K #ifdef CONFIG_AMD_PMF_DEBUG 16*506ed33dSShyam Sundar S K static const char *slider_as_str(unsigned int state) 17a82ebb3dSShyam Sundar S K { 18a82ebb3dSShyam Sundar S K switch (state) { 19a82ebb3dSShyam Sundar S K case POWER_MODE_PERFORMANCE: 20a82ebb3dSShyam Sundar S K return "PERFORMANCE"; 21a82ebb3dSShyam Sundar S K case POWER_MODE_BALANCED_POWER: 22a82ebb3dSShyam Sundar S K return "BALANCED_POWER"; 23a82ebb3dSShyam Sundar S K case POWER_MODE_POWER_SAVER: 24a82ebb3dSShyam Sundar S K return "POWER_SAVER"; 25a82ebb3dSShyam Sundar S K default: 26a82ebb3dSShyam Sundar S K return "Unknown Slider State"; 27a82ebb3dSShyam Sundar S K } 28a82ebb3dSShyam Sundar S K } 29a82ebb3dSShyam Sundar S K 30*506ed33dSShyam Sundar S K static const char *source_as_str(unsigned int state) 31a82ebb3dSShyam Sundar S K { 32a82ebb3dSShyam Sundar S K switch (state) { 33a82ebb3dSShyam Sundar S K case POWER_SOURCE_AC: 34a82ebb3dSShyam Sundar S K return "AC"; 35a82ebb3dSShyam Sundar S K case POWER_SOURCE_DC: 36a82ebb3dSShyam Sundar S K return "DC"; 37a82ebb3dSShyam Sundar S K default: 38a82ebb3dSShyam Sundar S K return "Unknown Power State"; 39a82ebb3dSShyam Sundar S K } 40a82ebb3dSShyam Sundar S K } 41a82ebb3dSShyam Sundar S K 42a82ebb3dSShyam Sundar S K static void amd_pmf_dump_sps_defaults(struct amd_pmf_static_slider_granular *data) 43a82ebb3dSShyam Sundar S K { 44a82ebb3dSShyam Sundar S K int i, j; 45a82ebb3dSShyam Sundar S K 46a82ebb3dSShyam Sundar S K pr_debug("Static Slider Data - BEGIN\n"); 47a82ebb3dSShyam Sundar S K 48a82ebb3dSShyam Sundar S K for (i = 0; i < POWER_SOURCE_MAX; i++) { 49a82ebb3dSShyam Sundar S K for (j = 0; j < POWER_MODE_MAX; j++) { 50a82ebb3dSShyam Sundar S K pr_debug("--- Source:%s Mode:%s ---\n", source_as_str(i), slider_as_str(j)); 51a82ebb3dSShyam Sundar S K pr_debug("SPL: %u mW\n", data->prop[i][j].spl); 52a82ebb3dSShyam Sundar S K pr_debug("SPPT: %u mW\n", data->prop[i][j].sppt); 53a82ebb3dSShyam Sundar S K pr_debug("SPPT_ApuOnly: %u mW\n", data->prop[i][j].sppt_apu_only); 54a82ebb3dSShyam Sundar S K pr_debug("FPPT: %u mW\n", data->prop[i][j].fppt); 55a82ebb3dSShyam Sundar S K pr_debug("STTMinLimit: %u mW\n", data->prop[i][j].stt_min); 56a82ebb3dSShyam Sundar S K pr_debug("STT_SkinTempLimit_APU: %u C\n", 57a82ebb3dSShyam Sundar S K data->prop[i][j].stt_skin_temp[STT_TEMP_APU]); 58a82ebb3dSShyam Sundar S K pr_debug("STT_SkinTempLimit_HS2: %u C\n", 59a82ebb3dSShyam Sundar S K data->prop[i][j].stt_skin_temp[STT_TEMP_HS2]); 60a82ebb3dSShyam Sundar S K } 61a82ebb3dSShyam Sundar S K } 62a82ebb3dSShyam Sundar S K 63a82ebb3dSShyam Sundar S K pr_debug("Static Slider Data - END\n"); 64a82ebb3dSShyam Sundar S K } 65a82ebb3dSShyam Sundar S K #else 66a82ebb3dSShyam Sundar S K static void amd_pmf_dump_sps_defaults(struct amd_pmf_static_slider_granular *data) {} 67a82ebb3dSShyam Sundar S K #endif 68a82ebb3dSShyam Sundar S K 694c71ae41SShyam Sundar S K static void amd_pmf_load_defaults_sps(struct amd_pmf_dev *dev) 704c71ae41SShyam Sundar S K { 714c71ae41SShyam Sundar S K struct apmf_static_slider_granular_output output; 724c71ae41SShyam Sundar S K int i, j, idx = 0; 734c71ae41SShyam Sundar S K 744c71ae41SShyam Sundar S K memset(&config_store, 0, sizeof(config_store)); 754c71ae41SShyam Sundar S K apmf_get_static_slider_granular(dev, &output); 764c71ae41SShyam Sundar S K 774c71ae41SShyam Sundar S K for (i = 0; i < POWER_SOURCE_MAX; i++) { 784c71ae41SShyam Sundar S K for (j = 0; j < POWER_MODE_MAX; j++) { 794c71ae41SShyam Sundar S K config_store.prop[i][j].spl = output.prop[idx].spl; 804c71ae41SShyam Sundar S K config_store.prop[i][j].sppt = output.prop[idx].sppt; 814c71ae41SShyam Sundar S K config_store.prop[i][j].sppt_apu_only = 824c71ae41SShyam Sundar S K output.prop[idx].sppt_apu_only; 834c71ae41SShyam Sundar S K config_store.prop[i][j].fppt = output.prop[idx].fppt; 844c71ae41SShyam Sundar S K config_store.prop[i][j].stt_min = output.prop[idx].stt_min; 854c71ae41SShyam Sundar S K config_store.prop[i][j].stt_skin_temp[STT_TEMP_APU] = 864c71ae41SShyam Sundar S K output.prop[idx].stt_skin_temp[STT_TEMP_APU]; 874c71ae41SShyam Sundar S K config_store.prop[i][j].stt_skin_temp[STT_TEMP_HS2] = 884c71ae41SShyam Sundar S K output.prop[idx].stt_skin_temp[STT_TEMP_HS2]; 894c71ae41SShyam Sundar S K config_store.prop[i][j].fan_id = output.prop[idx].fan_id; 904c71ae41SShyam Sundar S K idx++; 914c71ae41SShyam Sundar S K } 924c71ae41SShyam Sundar S K } 93a82ebb3dSShyam Sundar S K amd_pmf_dump_sps_defaults(&config_store); 944c71ae41SShyam Sundar S K } 954c71ae41SShyam Sundar S K 964c71ae41SShyam Sundar S K void amd_pmf_update_slider(struct amd_pmf_dev *dev, bool op, int idx, 974c71ae41SShyam Sundar S K struct amd_pmf_static_slider_granular *table) 984c71ae41SShyam Sundar S K { 994c71ae41SShyam Sundar S K int src = amd_pmf_get_power_source(); 1004c71ae41SShyam Sundar S K 1014c71ae41SShyam Sundar S K if (op == SLIDER_OP_SET) { 1024c71ae41SShyam Sundar S K amd_pmf_send_cmd(dev, SET_SPL, false, config_store.prop[src][idx].spl, NULL); 1034c71ae41SShyam Sundar S K amd_pmf_send_cmd(dev, SET_FPPT, false, config_store.prop[src][idx].fppt, NULL); 1044c71ae41SShyam Sundar S K amd_pmf_send_cmd(dev, SET_SPPT, false, config_store.prop[src][idx].sppt, NULL); 1054c71ae41SShyam Sundar S K amd_pmf_send_cmd(dev, SET_SPPT_APU_ONLY, false, 1064c71ae41SShyam Sundar S K config_store.prop[src][idx].sppt_apu_only, NULL); 1074c71ae41SShyam Sundar S K amd_pmf_send_cmd(dev, SET_STT_MIN_LIMIT, false, 1084c71ae41SShyam Sundar S K config_store.prop[src][idx].stt_min, NULL); 1094c71ae41SShyam Sundar S K amd_pmf_send_cmd(dev, SET_STT_LIMIT_APU, false, 1104c71ae41SShyam Sundar S K config_store.prop[src][idx].stt_skin_temp[STT_TEMP_APU], NULL); 1114c71ae41SShyam Sundar S K amd_pmf_send_cmd(dev, SET_STT_LIMIT_HS2, false, 1124c71ae41SShyam Sundar S K config_store.prop[src][idx].stt_skin_temp[STT_TEMP_HS2], NULL); 1134c71ae41SShyam Sundar S K } else if (op == SLIDER_OP_GET) { 1144c71ae41SShyam Sundar S K amd_pmf_send_cmd(dev, GET_SPL, true, ARG_NONE, &table->prop[src][idx].spl); 1154c71ae41SShyam Sundar S K amd_pmf_send_cmd(dev, GET_FPPT, true, ARG_NONE, &table->prop[src][idx].fppt); 1164c71ae41SShyam Sundar S K amd_pmf_send_cmd(dev, GET_SPPT, true, ARG_NONE, &table->prop[src][idx].sppt); 1174c71ae41SShyam Sundar S K amd_pmf_send_cmd(dev, GET_SPPT_APU_ONLY, true, ARG_NONE, 1184c71ae41SShyam Sundar S K &table->prop[src][idx].sppt_apu_only); 1194c71ae41SShyam Sundar S K amd_pmf_send_cmd(dev, GET_STT_MIN_LIMIT, true, ARG_NONE, 1204c71ae41SShyam Sundar S K &table->prop[src][idx].stt_min); 1214c71ae41SShyam Sundar S K amd_pmf_send_cmd(dev, GET_STT_LIMIT_APU, true, ARG_NONE, 1224c71ae41SShyam Sundar S K (u32 *)&table->prop[src][idx].stt_skin_temp[STT_TEMP_APU]); 1234c71ae41SShyam Sundar S K amd_pmf_send_cmd(dev, GET_STT_LIMIT_HS2, true, ARG_NONE, 1244c71ae41SShyam Sundar S K (u32 *)&table->prop[src][idx].stt_skin_temp[STT_TEMP_HS2]); 1254c71ae41SShyam Sundar S K } 1264c71ae41SShyam Sundar S K } 1274c71ae41SShyam Sundar S K 128c5258d39SShyam Sundar S K int amd_pmf_set_sps_power_limits(struct amd_pmf_dev *pmf) 129c5258d39SShyam Sundar S K { 130c5258d39SShyam Sundar S K int mode; 131c5258d39SShyam Sundar S K 132c5258d39SShyam Sundar S K mode = amd_pmf_get_pprof_modes(pmf); 133c5258d39SShyam Sundar S K if (mode < 0) 134c5258d39SShyam Sundar S K return mode; 135c5258d39SShyam Sundar S K 136c5258d39SShyam Sundar S K amd_pmf_update_slider(pmf, SLIDER_OP_SET, mode, NULL); 137c5258d39SShyam Sundar S K 138c5258d39SShyam Sundar S K return 0; 139c5258d39SShyam Sundar S K } 140c5258d39SShyam Sundar S K 14116909aa8SShyam Sundar S K bool is_pprof_balanced(struct amd_pmf_dev *pmf) 14216909aa8SShyam Sundar S K { 14316909aa8SShyam Sundar S K return (pmf->current_profile == PLATFORM_PROFILE_BALANCED) ? true : false; 14416909aa8SShyam Sundar S K } 14516909aa8SShyam Sundar S K 1464c71ae41SShyam Sundar S K static int amd_pmf_profile_get(struct platform_profile_handler *pprof, 1474c71ae41SShyam Sundar S K enum platform_profile_option *profile) 1484c71ae41SShyam Sundar S K { 1494c71ae41SShyam Sundar S K struct amd_pmf_dev *pmf = container_of(pprof, struct amd_pmf_dev, pprof); 1504c71ae41SShyam Sundar S K 1514c71ae41SShyam Sundar S K *profile = pmf->current_profile; 1524c71ae41SShyam Sundar S K return 0; 1534c71ae41SShyam Sundar S K } 1544c71ae41SShyam Sundar S K 155ea522b80SShyam Sundar S K int amd_pmf_get_pprof_modes(struct amd_pmf_dev *pmf) 1564c71ae41SShyam Sundar S K { 157ea522b80SShyam Sundar S K int mode; 1584c71ae41SShyam Sundar S K 1594c71ae41SShyam Sundar S K switch (pmf->current_profile) { 1604c71ae41SShyam Sundar S K case PLATFORM_PROFILE_PERFORMANCE: 1614c71ae41SShyam Sundar S K mode = POWER_MODE_PERFORMANCE; 1624c71ae41SShyam Sundar S K break; 1634c71ae41SShyam Sundar S K case PLATFORM_PROFILE_BALANCED: 1644c71ae41SShyam Sundar S K mode = POWER_MODE_BALANCED_POWER; 1654c71ae41SShyam Sundar S K break; 1664c71ae41SShyam Sundar S K case PLATFORM_PROFILE_LOW_POWER: 1674c71ae41SShyam Sundar S K mode = POWER_MODE_POWER_SAVER; 1684c71ae41SShyam Sundar S K break; 1694c71ae41SShyam Sundar S K default: 1704c71ae41SShyam Sundar S K dev_err(pmf->dev, "Unknown Platform Profile.\n"); 171ea522b80SShyam Sundar S K return -EOPNOTSUPP; 1724c71ae41SShyam Sundar S K } 1734c71ae41SShyam Sundar S K 1744c71ae41SShyam Sundar S K return mode; 1754c71ae41SShyam Sundar S K } 1764c71ae41SShyam Sundar S K 1774c71ae41SShyam Sundar S K static int amd_pmf_profile_set(struct platform_profile_handler *pprof, 1784c71ae41SShyam Sundar S K enum platform_profile_option profile) 1794c71ae41SShyam Sundar S K { 1804c71ae41SShyam Sundar S K struct amd_pmf_dev *pmf = container_of(pprof, struct amd_pmf_dev, pprof); 1814c71ae41SShyam Sundar S K 1824c71ae41SShyam Sundar S K pmf->current_profile = profile; 183ea522b80SShyam Sundar S K 184c5258d39SShyam Sundar S K return amd_pmf_set_sps_power_limits(pmf); 1854c71ae41SShyam Sundar S K } 1864c71ae41SShyam Sundar S K 1874c71ae41SShyam Sundar S K int amd_pmf_init_sps(struct amd_pmf_dev *dev) 1884c71ae41SShyam Sundar S K { 1894c71ae41SShyam Sundar S K int err; 1904c71ae41SShyam Sundar S K 1914c71ae41SShyam Sundar S K dev->current_profile = PLATFORM_PROFILE_BALANCED; 1924c71ae41SShyam Sundar S K amd_pmf_load_defaults_sps(dev); 1934c71ae41SShyam Sundar S K 194635f79bcSShyam Sundar S K /* update SPS balanced power mode thermals */ 195635f79bcSShyam Sundar S K amd_pmf_set_sps_power_limits(dev); 196635f79bcSShyam Sundar S K 1974c71ae41SShyam Sundar S K dev->pprof.profile_get = amd_pmf_profile_get; 1984c71ae41SShyam Sundar S K dev->pprof.profile_set = amd_pmf_profile_set; 1994c71ae41SShyam Sundar S K 2004c71ae41SShyam Sundar S K /* Setup supported modes */ 2014c71ae41SShyam Sundar S K set_bit(PLATFORM_PROFILE_LOW_POWER, dev->pprof.choices); 2024c71ae41SShyam Sundar S K set_bit(PLATFORM_PROFILE_BALANCED, dev->pprof.choices); 2034c71ae41SShyam Sundar S K set_bit(PLATFORM_PROFILE_PERFORMANCE, dev->pprof.choices); 2044c71ae41SShyam Sundar S K 2054c71ae41SShyam Sundar S K /* Create platform_profile structure and register */ 2064c71ae41SShyam Sundar S K err = platform_profile_register(&dev->pprof); 2074c71ae41SShyam Sundar S K if (err) 2084c71ae41SShyam Sundar S K dev_err(dev->dev, "Failed to register SPS support, this is most likely an SBIOS bug: %d\n", 2094c71ae41SShyam Sundar S K err); 2104c71ae41SShyam Sundar S K 2114c71ae41SShyam Sundar S K return err; 2124c71ae41SShyam Sundar S K } 2134c71ae41SShyam Sundar S K 2144c71ae41SShyam Sundar S K void amd_pmf_deinit_sps(struct amd_pmf_dev *dev) 2154c71ae41SShyam Sundar S K { 2164c71ae41SShyam Sundar S K platform_profile_remove(); 2174c71ae41SShyam Sundar S K } 218