xref: /linux/drivers/platform/x86/amd/pmf/sps.c (revision 4c71ae4144746eb467f6aaab0ff83e306f11d6af)
1*4c71ae41SShyam Sundar S K // SPDX-License-Identifier: GPL-2.0
2*4c71ae41SShyam Sundar S K /*
3*4c71ae41SShyam Sundar S K  * AMD Platform Management Framework (PMF) Driver
4*4c71ae41SShyam Sundar S K  *
5*4c71ae41SShyam Sundar S K  * Copyright (c) 2022, Advanced Micro Devices, Inc.
6*4c71ae41SShyam Sundar S K  * All Rights Reserved.
7*4c71ae41SShyam Sundar S K  *
8*4c71ae41SShyam Sundar S K  * Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
9*4c71ae41SShyam Sundar S K  */
10*4c71ae41SShyam Sundar S K 
11*4c71ae41SShyam Sundar S K #include "pmf.h"
12*4c71ae41SShyam Sundar S K 
13*4c71ae41SShyam Sundar S K static struct amd_pmf_static_slider_granular config_store;
14*4c71ae41SShyam Sundar S K 
15*4c71ae41SShyam Sundar S K static void amd_pmf_load_defaults_sps(struct amd_pmf_dev *dev)
16*4c71ae41SShyam Sundar S K {
17*4c71ae41SShyam Sundar S K 	struct apmf_static_slider_granular_output output;
18*4c71ae41SShyam Sundar S K 	int i, j, idx = 0;
19*4c71ae41SShyam Sundar S K 
20*4c71ae41SShyam Sundar S K 	memset(&config_store, 0, sizeof(config_store));
21*4c71ae41SShyam Sundar S K 	apmf_get_static_slider_granular(dev, &output);
22*4c71ae41SShyam Sundar S K 
23*4c71ae41SShyam Sundar S K 	for (i = 0; i < POWER_SOURCE_MAX; i++) {
24*4c71ae41SShyam Sundar S K 		for (j = 0; j < POWER_MODE_MAX; j++) {
25*4c71ae41SShyam Sundar S K 			config_store.prop[i][j].spl = output.prop[idx].spl;
26*4c71ae41SShyam Sundar S K 			config_store.prop[i][j].sppt = output.prop[idx].sppt;
27*4c71ae41SShyam Sundar S K 			config_store.prop[i][j].sppt_apu_only =
28*4c71ae41SShyam Sundar S K 						output.prop[idx].sppt_apu_only;
29*4c71ae41SShyam Sundar S K 			config_store.prop[i][j].fppt = output.prop[idx].fppt;
30*4c71ae41SShyam Sundar S K 			config_store.prop[i][j].stt_min = output.prop[idx].stt_min;
31*4c71ae41SShyam Sundar S K 			config_store.prop[i][j].stt_skin_temp[STT_TEMP_APU] =
32*4c71ae41SShyam Sundar S K 					output.prop[idx].stt_skin_temp[STT_TEMP_APU];
33*4c71ae41SShyam Sundar S K 			config_store.prop[i][j].stt_skin_temp[STT_TEMP_HS2] =
34*4c71ae41SShyam Sundar S K 					output.prop[idx].stt_skin_temp[STT_TEMP_HS2];
35*4c71ae41SShyam Sundar S K 			config_store.prop[i][j].fan_id = output.prop[idx].fan_id;
36*4c71ae41SShyam Sundar S K 			idx++;
37*4c71ae41SShyam Sundar S K 		}
38*4c71ae41SShyam Sundar S K 	}
39*4c71ae41SShyam Sundar S K }
40*4c71ae41SShyam Sundar S K 
41*4c71ae41SShyam Sundar S K void amd_pmf_update_slider(struct amd_pmf_dev *dev, bool op, int idx,
42*4c71ae41SShyam Sundar S K 			   struct amd_pmf_static_slider_granular *table)
43*4c71ae41SShyam Sundar S K {
44*4c71ae41SShyam Sundar S K 	int src = amd_pmf_get_power_source();
45*4c71ae41SShyam Sundar S K 
46*4c71ae41SShyam Sundar S K 	if (op == SLIDER_OP_SET) {
47*4c71ae41SShyam Sundar S K 		amd_pmf_send_cmd(dev, SET_SPL, false, config_store.prop[src][idx].spl, NULL);
48*4c71ae41SShyam Sundar S K 		amd_pmf_send_cmd(dev, SET_FPPT, false, config_store.prop[src][idx].fppt, NULL);
49*4c71ae41SShyam Sundar S K 		amd_pmf_send_cmd(dev, SET_SPPT, false, config_store.prop[src][idx].sppt, NULL);
50*4c71ae41SShyam Sundar S K 		amd_pmf_send_cmd(dev, SET_SPPT_APU_ONLY, false,
51*4c71ae41SShyam Sundar S K 				 config_store.prop[src][idx].sppt_apu_only, NULL);
52*4c71ae41SShyam Sundar S K 		amd_pmf_send_cmd(dev, SET_STT_MIN_LIMIT, false,
53*4c71ae41SShyam Sundar S K 				 config_store.prop[src][idx].stt_min, NULL);
54*4c71ae41SShyam Sundar S K 		amd_pmf_send_cmd(dev, SET_STT_LIMIT_APU, false,
55*4c71ae41SShyam Sundar S K 				 config_store.prop[src][idx].stt_skin_temp[STT_TEMP_APU], NULL);
56*4c71ae41SShyam Sundar S K 		amd_pmf_send_cmd(dev, SET_STT_LIMIT_HS2, false,
57*4c71ae41SShyam Sundar S K 				 config_store.prop[src][idx].stt_skin_temp[STT_TEMP_HS2], NULL);
58*4c71ae41SShyam Sundar S K 	} else if (op == SLIDER_OP_GET) {
59*4c71ae41SShyam Sundar S K 		amd_pmf_send_cmd(dev, GET_SPL, true, ARG_NONE, &table->prop[src][idx].spl);
60*4c71ae41SShyam Sundar S K 		amd_pmf_send_cmd(dev, GET_FPPT, true, ARG_NONE, &table->prop[src][idx].fppt);
61*4c71ae41SShyam Sundar S K 		amd_pmf_send_cmd(dev, GET_SPPT, true, ARG_NONE, &table->prop[src][idx].sppt);
62*4c71ae41SShyam Sundar S K 		amd_pmf_send_cmd(dev, GET_SPPT_APU_ONLY, true, ARG_NONE,
63*4c71ae41SShyam Sundar S K 				 &table->prop[src][idx].sppt_apu_only);
64*4c71ae41SShyam Sundar S K 		amd_pmf_send_cmd(dev, GET_STT_MIN_LIMIT, true, ARG_NONE,
65*4c71ae41SShyam Sundar S K 				 &table->prop[src][idx].stt_min);
66*4c71ae41SShyam Sundar S K 		amd_pmf_send_cmd(dev, GET_STT_LIMIT_APU, true, ARG_NONE,
67*4c71ae41SShyam Sundar S K 				 (u32 *)&table->prop[src][idx].stt_skin_temp[STT_TEMP_APU]);
68*4c71ae41SShyam Sundar S K 		amd_pmf_send_cmd(dev, GET_STT_LIMIT_HS2, true, ARG_NONE,
69*4c71ae41SShyam Sundar S K 				 (u32 *)&table->prop[src][idx].stt_skin_temp[STT_TEMP_HS2]);
70*4c71ae41SShyam Sundar S K 	}
71*4c71ae41SShyam Sundar S K }
72*4c71ae41SShyam Sundar S K 
73*4c71ae41SShyam Sundar S K static int amd_pmf_profile_get(struct platform_profile_handler *pprof,
74*4c71ae41SShyam Sundar S K 			       enum platform_profile_option *profile)
75*4c71ae41SShyam Sundar S K {
76*4c71ae41SShyam Sundar S K 	struct amd_pmf_dev *pmf = container_of(pprof, struct amd_pmf_dev, pprof);
77*4c71ae41SShyam Sundar S K 
78*4c71ae41SShyam Sundar S K 	*profile = pmf->current_profile;
79*4c71ae41SShyam Sundar S K 	return 0;
80*4c71ae41SShyam Sundar S K }
81*4c71ae41SShyam Sundar S K 
82*4c71ae41SShyam Sundar S K u8 amd_pmf_get_pprof_modes(struct amd_pmf_dev *pmf)
83*4c71ae41SShyam Sundar S K {
84*4c71ae41SShyam Sundar S K 	u8 mode;
85*4c71ae41SShyam Sundar S K 
86*4c71ae41SShyam Sundar S K 	switch (pmf->current_profile) {
87*4c71ae41SShyam Sundar S K 	case PLATFORM_PROFILE_PERFORMANCE:
88*4c71ae41SShyam Sundar S K 		mode = POWER_MODE_PERFORMANCE;
89*4c71ae41SShyam Sundar S K 		break;
90*4c71ae41SShyam Sundar S K 	case PLATFORM_PROFILE_BALANCED:
91*4c71ae41SShyam Sundar S K 		mode = POWER_MODE_BALANCED_POWER;
92*4c71ae41SShyam Sundar S K 		break;
93*4c71ae41SShyam Sundar S K 	case PLATFORM_PROFILE_LOW_POWER:
94*4c71ae41SShyam Sundar S K 		mode = POWER_MODE_POWER_SAVER;
95*4c71ae41SShyam Sundar S K 		break;
96*4c71ae41SShyam Sundar S K 	default:
97*4c71ae41SShyam Sundar S K 		dev_err(pmf->dev, "Unknown Platform Profile.\n");
98*4c71ae41SShyam Sundar S K 		break;
99*4c71ae41SShyam Sundar S K 	}
100*4c71ae41SShyam Sundar S K 
101*4c71ae41SShyam Sundar S K 	return mode;
102*4c71ae41SShyam Sundar S K }
103*4c71ae41SShyam Sundar S K 
104*4c71ae41SShyam Sundar S K static int amd_pmf_profile_set(struct platform_profile_handler *pprof,
105*4c71ae41SShyam Sundar S K 			       enum platform_profile_option profile)
106*4c71ae41SShyam Sundar S K {
107*4c71ae41SShyam Sundar S K 	struct amd_pmf_dev *pmf = container_of(pprof, struct amd_pmf_dev, pprof);
108*4c71ae41SShyam Sundar S K 	u8 mode;
109*4c71ae41SShyam Sundar S K 
110*4c71ae41SShyam Sundar S K 	pmf->current_profile = profile;
111*4c71ae41SShyam Sundar S K 	mode = amd_pmf_get_pprof_modes(pmf);
112*4c71ae41SShyam Sundar S K 	amd_pmf_update_slider(pmf, SLIDER_OP_SET, mode, NULL);
113*4c71ae41SShyam Sundar S K 	return 0;
114*4c71ae41SShyam Sundar S K }
115*4c71ae41SShyam Sundar S K 
116*4c71ae41SShyam Sundar S K int amd_pmf_init_sps(struct amd_pmf_dev *dev)
117*4c71ae41SShyam Sundar S K {
118*4c71ae41SShyam Sundar S K 	int err;
119*4c71ae41SShyam Sundar S K 
120*4c71ae41SShyam Sundar S K 	dev->current_profile = PLATFORM_PROFILE_BALANCED;
121*4c71ae41SShyam Sundar S K 	amd_pmf_load_defaults_sps(dev);
122*4c71ae41SShyam Sundar S K 
123*4c71ae41SShyam Sundar S K 	dev->pprof.profile_get = amd_pmf_profile_get;
124*4c71ae41SShyam Sundar S K 	dev->pprof.profile_set = amd_pmf_profile_set;
125*4c71ae41SShyam Sundar S K 
126*4c71ae41SShyam Sundar S K 	/* Setup supported modes */
127*4c71ae41SShyam Sundar S K 	set_bit(PLATFORM_PROFILE_LOW_POWER, dev->pprof.choices);
128*4c71ae41SShyam Sundar S K 	set_bit(PLATFORM_PROFILE_BALANCED, dev->pprof.choices);
129*4c71ae41SShyam Sundar S K 	set_bit(PLATFORM_PROFILE_PERFORMANCE, dev->pprof.choices);
130*4c71ae41SShyam Sundar S K 
131*4c71ae41SShyam Sundar S K 	/* Create platform_profile structure and register */
132*4c71ae41SShyam Sundar S K 	err = platform_profile_register(&dev->pprof);
133*4c71ae41SShyam Sundar S K 	if (err)
134*4c71ae41SShyam Sundar S K 		dev_err(dev->dev, "Failed to register SPS support, this is most likely an SBIOS bug: %d\n",
135*4c71ae41SShyam Sundar S K 			err);
136*4c71ae41SShyam Sundar S K 
137*4c71ae41SShyam Sundar S K 	return err;
138*4c71ae41SShyam Sundar S K }
139*4c71ae41SShyam Sundar S K 
140*4c71ae41SShyam Sundar S K void amd_pmf_deinit_sps(struct amd_pmf_dev *dev)
141*4c71ae41SShyam Sundar S K {
142*4c71ae41SShyam Sundar S K 	platform_profile_remove();
143*4c71ae41SShyam Sundar S K }
144