brintos

brintos / linux-shallow public Read only

0
0
Text · 12.3 KiB · 92f7fb2 Raw
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