1 // SPDX-License-Identifier: GPL-2.0
3 * AMD Platform Management Framework (PMF) Driver
5 * Copyright (c) 2022, Advanced Micro Devices, Inc.
8 * Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
13 static struct amd_pmf_static_slider_granular_v2 config_store_v2
;
14 static struct amd_pmf_static_slider_granular config_store
;
15 static struct amd_pmf_apts_granular apts_config_store
;
17 #ifdef CONFIG_AMD_PMF_DEBUG
18 static const char *slider_v2_as_str(unsigned int state
)
21 case POWER_MODE_BEST_PERFORMANCE
:
22 return "Best Performance";
23 case POWER_MODE_BALANCED
:
25 case POWER_MODE_BEST_POWER_EFFICIENCY
:
26 return "Best Power Efficiency";
27 case POWER_MODE_ENERGY_SAVE
:
30 return "Unknown Power Mode";
34 static const char *slider_as_str(unsigned int state
)
37 case POWER_MODE_PERFORMANCE
:
39 case POWER_MODE_BALANCED_POWER
:
40 return "BALANCED_POWER";
41 case POWER_MODE_POWER_SAVER
:
44 return "Unknown Slider State";
48 const char *amd_pmf_source_as_str(unsigned int state
)
56 return "Unknown Power State";
60 static void amd_pmf_dump_sps_defaults(struct amd_pmf_static_slider_granular
*data
)
64 pr_debug("Static Slider Data - BEGIN\n");
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
),
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
]);
82 pr_debug("Static Slider Data - END\n");
85 static void amd_pmf_dump_sps_defaults_v2(struct amd_pmf_static_slider_granular_v2
*data
)
89 pr_debug("Static Slider APTS state index data - BEGIN");
90 pr_debug("size: %u\n", data
->size
);
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
]);
97 pr_debug("Static Slider APTS state index data - END\n");
100 static void amd_pmf_dump_apts_sps_defaults(struct amd_pmf_apts_granular
*info
)
104 pr_debug("Static Slider APTS index default values data - BEGIN");
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
);
116 pr_debug("Static Slider APTS index default values data - END");
119 static void amd_pmf_dump_sps_defaults(struct amd_pmf_static_slider_granular
*data
) {}
120 static void amd_pmf_dump_sps_defaults_v2(struct amd_pmf_static_slider_granular_v2
*data
) {}
121 static void amd_pmf_dump_apts_sps_defaults(struct amd_pmf_apts_granular
*info
) {}
124 static void amd_pmf_load_apts_defaults_sps_v2(struct amd_pmf_dev
*pdev
)
126 struct amd_pmf_apts_granular_output output
;
127 struct amd_pmf_apts_output
*ps
;
130 memset(&apts_config_store
, 0, sizeof(apts_config_store
));
132 ps
= apts_config_store
.val
;
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
;
145 amd_pmf_dump_apts_sps_defaults(&apts_config_store
);
148 static void amd_pmf_load_defaults_sps_v2(struct amd_pmf_dev
*dev
)
150 struct apmf_static_slider_granular_output_v2 output
;
153 memset(&config_store_v2
, 0, sizeof(config_store_v2
));
154 apmf_get_static_slider_granular_v2(dev
, &output
);
156 config_store_v2
.size
= output
.size
;
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
];
163 amd_pmf_dump_sps_defaults_v2(&config_store_v2
);
166 static void amd_pmf_load_defaults_sps(struct amd_pmf_dev
*dev
)
168 struct apmf_static_slider_granular_output output
;
171 memset(&config_store
, 0, sizeof(config_store
));
172 apmf_get_static_slider_granular(dev
, &output
);
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
;
190 amd_pmf_dump_sps_defaults(&config_store
);
193 static void amd_pmf_update_slider_v2(struct amd_pmf_dev
*dev
, int idx
)
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
);
206 void amd_pmf_update_slider(struct amd_pmf_dev
*dev
, bool op
, int idx
,
207 struct amd_pmf_static_slider_granular
*table
)
209 int src
= amd_pmf_get_power_source();
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
]);
238 static int amd_pmf_update_sps_power_limits_v2(struct amd_pmf_dev
*pdev
, int pwr_mode
)
242 src
= amd_pmf_get_power_source();
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
);
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
);
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
);
264 int amd_pmf_set_sps_power_limits(struct amd_pmf_dev
*pmf
)
268 mode
= amd_pmf_get_pprof_modes(pmf
);
272 if (pmf
->pmf_if_version
== PMF_IF_V2
)
273 return amd_pmf_update_sps_power_limits_v2(pmf
, mode
);
275 amd_pmf_update_slider(pmf
, SLIDER_OP_SET
, mode
, NULL
);
280 bool is_pprof_balanced(struct amd_pmf_dev
*pmf
)
282 return (pmf
->current_profile
== PLATFORM_PROFILE_BALANCED
) ? true : false;
285 static int amd_pmf_profile_get(struct device
*dev
,
286 enum platform_profile_option
*profile
)
288 struct amd_pmf_dev
*pmf
= dev_get_drvdata(dev
);
290 *profile
= pmf
->current_profile
;
294 int amd_pmf_get_pprof_modes(struct amd_pmf_dev
*pmf
)
298 switch (pmf
->current_profile
) {
299 case PLATFORM_PROFILE_PERFORMANCE
:
300 mode
= POWER_MODE_PERFORMANCE
;
302 case PLATFORM_PROFILE_BALANCED
:
303 mode
= POWER_MODE_BALANCED_POWER
;
305 case PLATFORM_PROFILE_LOW_POWER
:
306 mode
= POWER_MODE_POWER_SAVER
;
309 dev_err(pmf
->dev
, "Unknown Platform Profile.\n");
316 int amd_pmf_power_slider_update_event(struct amd_pmf_dev
*dev
)
322 mode
= amd_pmf_get_pprof_modes(dev
);
326 src
= amd_pmf_get_power_source();
328 if (src
== POWER_SOURCE_AC
) {
330 case POWER_MODE_PERFORMANCE
:
331 flag
|= BIT(AC_BEST_PERF
);
333 case POWER_MODE_BALANCED_POWER
:
334 flag
|= BIT(AC_BETTER_PERF
);
336 case POWER_MODE_POWER_SAVER
:
337 flag
|= BIT(AC_BETTER_BATTERY
);
340 dev_err(dev
->dev
, "unsupported platform profile\n");
344 } else if (src
== POWER_SOURCE_DC
) {
346 case POWER_MODE_PERFORMANCE
:
347 flag
|= BIT(DC_BEST_PERF
);
349 case POWER_MODE_BALANCED_POWER
:
350 flag
|= BIT(DC_BETTER_PERF
);
352 case POWER_MODE_POWER_SAVER
:
353 flag
|= BIT(DC_BATTERY_SAVER
);
356 dev_err(dev
->dev
, "unsupported platform profile\n");
361 apmf_os_power_slider_update(dev
, flag
);
366 static int amd_pmf_profile_set(struct device
*dev
,
367 enum platform_profile_option profile
)
369 struct amd_pmf_dev
*pmf
= dev_get_drvdata(dev
);
372 pmf
->current_profile
= profile
;
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
);
381 if (is_apmf_func_supported(pmf
, APMF_FUNC_STATIC_SLIDER_GRANULAR
)) {
382 ret
= amd_pmf_set_sps_power_limits(pmf
);
390 static int amd_pmf_profile_probe(void *drvdata
, unsigned long *choices
)
392 set_bit(PLATFORM_PROFILE_LOW_POWER
, choices
);
393 set_bit(PLATFORM_PROFILE_BALANCED
, choices
);
394 set_bit(PLATFORM_PROFILE_PERFORMANCE
, choices
);
399 static const struct platform_profile_ops amd_pmf_profile_ops
= {
400 .probe
= amd_pmf_profile_probe
,
401 .profile_get
= amd_pmf_profile_get
,
402 .profile_set
= amd_pmf_profile_set
,
405 int amd_pmf_init_sps(struct amd_pmf_dev
*dev
)
407 dev
->current_profile
= PLATFORM_PROFILE_BALANCED
;
409 if (is_apmf_func_supported(dev
, APMF_FUNC_STATIC_SLIDER_GRANULAR
)) {
410 if (dev
->pmf_if_version
== PMF_IF_V2
) {
411 amd_pmf_load_defaults_sps_v2(dev
);
412 amd_pmf_load_apts_defaults_sps_v2(dev
);
414 amd_pmf_load_defaults_sps(dev
);
417 /* update SPS balanced power mode thermals */
418 amd_pmf_set_sps_power_limits(dev
);
421 /* Create platform_profile structure and register */
422 dev
->ppdev
= devm_platform_profile_register(dev
->dev
, "amd-pmf", dev
,
423 &amd_pmf_profile_ops
);
424 if (IS_ERR(dev
->ppdev
))
425 dev_err(dev
->dev
, "Failed to register SPS support, this is most likely an SBIOS bug: %ld\n",
426 PTR_ERR(dev
->ppdev
));
428 return PTR_ERR_OR_ZERO(dev
->ppdev
);