2 * Copyright 2016 Advanced Micro Devices, Inc.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
24 #include "smu7_hwmgr.h"
25 #include "smu7_clockpowergating.h"
26 #include "smu7_common.h"
28 static int smu7_enable_disable_uvd_dpm(struct pp_hwmgr
*hwmgr
, bool enable
)
30 return smum_send_msg_to_smc(hwmgr
->smumgr
, enable
?
31 PPSMC_MSG_UVDDPM_Enable
:
32 PPSMC_MSG_UVDDPM_Disable
);
35 static int smu7_enable_disable_vce_dpm(struct pp_hwmgr
*hwmgr
, bool enable
)
37 return smum_send_msg_to_smc(hwmgr
->smumgr
, enable
?
38 PPSMC_MSG_VCEDPM_Enable
:
39 PPSMC_MSG_VCEDPM_Disable
);
42 static int smu7_enable_disable_samu_dpm(struct pp_hwmgr
*hwmgr
, bool enable
)
44 return smum_send_msg_to_smc(hwmgr
->smumgr
, enable
?
45 PPSMC_MSG_SAMUDPM_Enable
:
46 PPSMC_MSG_SAMUDPM_Disable
);
49 static int smu7_update_uvd_dpm(struct pp_hwmgr
*hwmgr
, bool bgate
)
52 smum_update_smc_table(hwmgr
, SMU_UVD_TABLE
);
53 return smu7_enable_disable_uvd_dpm(hwmgr
, !bgate
);
56 static int smu7_update_vce_dpm(struct pp_hwmgr
*hwmgr
, bool bgate
)
59 smum_update_smc_table(hwmgr
, SMU_VCE_TABLE
);
60 return smu7_enable_disable_vce_dpm(hwmgr
, !bgate
);
63 static int smu7_update_samu_dpm(struct pp_hwmgr
*hwmgr
, bool bgate
)
66 smum_update_smc_table(hwmgr
, SMU_SAMU_TABLE
);
67 return smu7_enable_disable_samu_dpm(hwmgr
, !bgate
);
70 int smu7_powerdown_uvd(struct pp_hwmgr
*hwmgr
)
72 if (phm_cf_want_uvd_power_gating(hwmgr
))
73 return smum_send_msg_to_smc(hwmgr
->smumgr
,
74 PPSMC_MSG_UVDPowerOFF
);
78 static int smu7_powerup_uvd(struct pp_hwmgr
*hwmgr
)
80 if (phm_cf_want_uvd_power_gating(hwmgr
)) {
81 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
82 PHM_PlatformCaps_UVDDynamicPowerGating
)) {
83 return smum_send_msg_to_smc_with_parameter(hwmgr
->smumgr
,
84 PPSMC_MSG_UVDPowerON
, 1);
86 return smum_send_msg_to_smc_with_parameter(hwmgr
->smumgr
,
87 PPSMC_MSG_UVDPowerON
, 0);
94 static int smu7_powerdown_vce(struct pp_hwmgr
*hwmgr
)
96 if (phm_cf_want_vce_power_gating(hwmgr
))
97 return smum_send_msg_to_smc(hwmgr
->smumgr
,
98 PPSMC_MSG_VCEPowerOFF
);
102 static int smu7_powerup_vce(struct pp_hwmgr
*hwmgr
)
104 if (phm_cf_want_vce_power_gating(hwmgr
))
105 return smum_send_msg_to_smc(hwmgr
->smumgr
,
106 PPSMC_MSG_VCEPowerON
);
110 static int smu7_powerdown_samu(struct pp_hwmgr
*hwmgr
)
112 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
113 PHM_PlatformCaps_SamuPowerGating
))
114 return smum_send_msg_to_smc(hwmgr
->smumgr
,
115 PPSMC_MSG_SAMPowerOFF
);
119 static int smu7_powerup_samu(struct pp_hwmgr
*hwmgr
)
121 if (phm_cap_enabled(hwmgr
->platform_descriptor
.platformCaps
,
122 PHM_PlatformCaps_SamuPowerGating
))
123 return smum_send_msg_to_smc(hwmgr
->smumgr
,
124 PPSMC_MSG_SAMPowerON
);
128 int smu7_disable_clock_power_gating(struct pp_hwmgr
*hwmgr
)
130 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
132 data
->uvd_power_gated
= false;
133 data
->vce_power_gated
= false;
134 data
->samu_power_gated
= false;
136 smu7_powerup_uvd(hwmgr
);
137 smu7_powerup_vce(hwmgr
);
138 smu7_powerup_samu(hwmgr
);
143 int smu7_powergate_uvd(struct pp_hwmgr
*hwmgr
, bool bgate
)
145 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
147 data
->uvd_power_gated
= bgate
;
150 cgs_set_powergating_state(hwmgr
->device
,
151 AMD_IP_BLOCK_TYPE_UVD
,
153 cgs_set_clockgating_state(hwmgr
->device
,
154 AMD_IP_BLOCK_TYPE_UVD
,
156 smu7_update_uvd_dpm(hwmgr
, true);
157 smu7_powerdown_uvd(hwmgr
);
159 smu7_powerup_uvd(hwmgr
);
160 cgs_set_clockgating_state(hwmgr
->device
,
161 AMD_IP_BLOCK_TYPE_UVD
,
162 AMD_CG_STATE_UNGATE
);
163 cgs_set_powergating_state(hwmgr
->device
,
164 AMD_IP_BLOCK_TYPE_UVD
,
165 AMD_CG_STATE_UNGATE
);
166 smu7_update_uvd_dpm(hwmgr
, false);
172 int smu7_powergate_vce(struct pp_hwmgr
*hwmgr
, bool bgate
)
174 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
176 data
->vce_power_gated
= bgate
;
179 cgs_set_powergating_state(hwmgr
->device
,
180 AMD_IP_BLOCK_TYPE_VCE
,
181 AMD_PG_STATE_UNGATE
);
182 cgs_set_clockgating_state(hwmgr
->device
,
183 AMD_IP_BLOCK_TYPE_VCE
,
185 smu7_update_vce_dpm(hwmgr
, true);
186 smu7_powerdown_vce(hwmgr
);
188 smu7_powerup_vce(hwmgr
);
189 cgs_set_clockgating_state(hwmgr
->device
,
190 AMD_IP_BLOCK_TYPE_VCE
,
191 AMD_CG_STATE_UNGATE
);
192 cgs_set_powergating_state(hwmgr
->device
,
193 AMD_IP_BLOCK_TYPE_VCE
,
194 AMD_PG_STATE_UNGATE
);
195 smu7_update_vce_dpm(hwmgr
, false);
200 int smu7_powergate_samu(struct pp_hwmgr
*hwmgr
, bool bgate
)
202 struct smu7_hwmgr
*data
= (struct smu7_hwmgr
*)(hwmgr
->backend
);
204 if (data
->samu_power_gated
== bgate
)
207 data
->samu_power_gated
= bgate
;
210 smu7_update_samu_dpm(hwmgr
, true);
211 smu7_powerdown_samu(hwmgr
);
213 smu7_powerup_samu(hwmgr
);
214 smu7_update_samu_dpm(hwmgr
, false);
220 int smu7_update_clock_gatings(struct pp_hwmgr
*hwmgr
,
221 const uint32_t *msg_id
)
226 if (!(hwmgr
->feature_mask
& PP_ENABLE_GFX_CG_THRU_SMU
))
229 switch ((*msg_id
& PP_GROUP_MASK
) >> PP_GROUP_SHIFT
) {
231 switch ((*msg_id
& PP_BLOCK_MASK
) >> PP_BLOCK_SHIFT
) {
232 case PP_BLOCK_GFX_CG
:
233 if (PP_STATE_SUPPORT_CG
& *msg_id
) {
234 msg
= ((*msg_id
& PP_STATE_MASK
) & PP_STATE_CG
) ?
235 PPSMC_MSG_EnableClockGatingFeature
:
236 PPSMC_MSG_DisableClockGatingFeature
;
237 value
= CG_GFX_CGCG_MASK
;
239 if (smum_send_msg_to_smc_with_parameter(
240 hwmgr
->smumgr
, msg
, value
))
243 if (PP_STATE_SUPPORT_LS
& *msg_id
) {
244 msg
= (*msg_id
& PP_STATE_MASK
) & PP_STATE_LS
245 ? PPSMC_MSG_EnableClockGatingFeature
246 : PPSMC_MSG_DisableClockGatingFeature
;
247 value
= CG_GFX_CGLS_MASK
;
249 if (smum_send_msg_to_smc_with_parameter(
250 hwmgr
->smumgr
, msg
, value
))
255 case PP_BLOCK_GFX_3D
:
256 if (PP_STATE_SUPPORT_CG
& *msg_id
) {
257 msg
= ((*msg_id
& PP_STATE_MASK
) & PP_STATE_CG
) ?
258 PPSMC_MSG_EnableClockGatingFeature
:
259 PPSMC_MSG_DisableClockGatingFeature
;
260 value
= CG_GFX_3DCG_MASK
;
262 if (smum_send_msg_to_smc_with_parameter(
263 hwmgr
->smumgr
, msg
, value
))
267 if (PP_STATE_SUPPORT_LS
& *msg_id
) {
268 msg
= (*msg_id
& PP_STATE_MASK
) & PP_STATE_LS
?
269 PPSMC_MSG_EnableClockGatingFeature
:
270 PPSMC_MSG_DisableClockGatingFeature
;
271 value
= CG_GFX_3DLS_MASK
;
273 if (smum_send_msg_to_smc_with_parameter(
274 hwmgr
->smumgr
, msg
, value
))
279 case PP_BLOCK_GFX_RLC
:
280 if (PP_STATE_SUPPORT_LS
& *msg_id
) {
281 msg
= (*msg_id
& PP_STATE_MASK
) & PP_STATE_LS
?
282 PPSMC_MSG_EnableClockGatingFeature
:
283 PPSMC_MSG_DisableClockGatingFeature
;
284 value
= CG_GFX_RLC_LS_MASK
;
286 if (smum_send_msg_to_smc_with_parameter(
287 hwmgr
->smumgr
, msg
, value
))
292 case PP_BLOCK_GFX_CP
:
293 if (PP_STATE_SUPPORT_LS
& *msg_id
) {
294 msg
= (*msg_id
& PP_STATE_MASK
) & PP_STATE_LS
?
295 PPSMC_MSG_EnableClockGatingFeature
:
296 PPSMC_MSG_DisableClockGatingFeature
;
297 value
= CG_GFX_CP_LS_MASK
;
299 if (smum_send_msg_to_smc_with_parameter(
300 hwmgr
->smumgr
, msg
, value
))
305 case PP_BLOCK_GFX_MG
:
306 if (PP_STATE_SUPPORT_CG
& *msg_id
) {
307 msg
= ((*msg_id
& PP_STATE_MASK
) & PP_STATE_CG
) ?
308 PPSMC_MSG_EnableClockGatingFeature
:
309 PPSMC_MSG_DisableClockGatingFeature
;
310 value
= (CG_CPF_MGCG_MASK
| CG_RLC_MGCG_MASK
|
311 CG_GFX_OTHERS_MGCG_MASK
);
313 if (smum_send_msg_to_smc_with_parameter(
314 hwmgr
->smumgr
, msg
, value
))
325 switch ((*msg_id
& PP_BLOCK_MASK
) >> PP_BLOCK_SHIFT
) {
326 case PP_BLOCK_SYS_BIF
:
327 if (PP_STATE_SUPPORT_CG
& *msg_id
) {
328 msg
= (*msg_id
& PP_STATE_MASK
) & PP_STATE_CG
?
329 PPSMC_MSG_EnableClockGatingFeature
:
330 PPSMC_MSG_DisableClockGatingFeature
;
331 value
= CG_SYS_BIF_MGCG_MASK
;
333 if (smum_send_msg_to_smc_with_parameter(
334 hwmgr
->smumgr
, msg
, value
))
337 if (PP_STATE_SUPPORT_LS
& *msg_id
) {
338 msg
= (*msg_id
& PP_STATE_MASK
) & PP_STATE_LS
?
339 PPSMC_MSG_EnableClockGatingFeature
:
340 PPSMC_MSG_DisableClockGatingFeature
;
341 value
= CG_SYS_BIF_MGLS_MASK
;
343 if (smum_send_msg_to_smc_with_parameter(
344 hwmgr
->smumgr
, msg
, value
))
349 case PP_BLOCK_SYS_MC
:
350 if (PP_STATE_SUPPORT_CG
& *msg_id
) {
351 msg
= ((*msg_id
& PP_STATE_MASK
) & PP_STATE_CG
) ?
352 PPSMC_MSG_EnableClockGatingFeature
:
353 PPSMC_MSG_DisableClockGatingFeature
;
354 value
= CG_SYS_MC_MGCG_MASK
;
356 if (smum_send_msg_to_smc_with_parameter(
357 hwmgr
->smumgr
, msg
, value
))
361 if (PP_STATE_SUPPORT_LS
& *msg_id
) {
362 msg
= (*msg_id
& PP_STATE_MASK
) & PP_STATE_LS
?
363 PPSMC_MSG_EnableClockGatingFeature
:
364 PPSMC_MSG_DisableClockGatingFeature
;
365 value
= CG_SYS_MC_MGLS_MASK
;
367 if (smum_send_msg_to_smc_with_parameter(
368 hwmgr
->smumgr
, msg
, value
))
373 case PP_BLOCK_SYS_DRM
:
374 if (PP_STATE_SUPPORT_CG
& *msg_id
) {
375 msg
= (*msg_id
& PP_STATE_MASK
) & PP_STATE_CG
?
376 PPSMC_MSG_EnableClockGatingFeature
:
377 PPSMC_MSG_DisableClockGatingFeature
;
378 value
= CG_SYS_DRM_MGCG_MASK
;
380 if (smum_send_msg_to_smc_with_parameter(
381 hwmgr
->smumgr
, msg
, value
))
384 if (PP_STATE_SUPPORT_LS
& *msg_id
) {
385 msg
= (*msg_id
& PP_STATE_MASK
) & PP_STATE_LS
?
386 PPSMC_MSG_EnableClockGatingFeature
:
387 PPSMC_MSG_DisableClockGatingFeature
;
388 value
= CG_SYS_DRM_MGLS_MASK
;
390 if (smum_send_msg_to_smc_with_parameter(
391 hwmgr
->smumgr
, msg
, value
))
396 case PP_BLOCK_SYS_HDP
:
397 if (PP_STATE_SUPPORT_CG
& *msg_id
) {
398 msg
= ((*msg_id
& PP_STATE_MASK
) & PP_STATE_CG
) ?
399 PPSMC_MSG_EnableClockGatingFeature
:
400 PPSMC_MSG_DisableClockGatingFeature
;
401 value
= CG_SYS_HDP_MGCG_MASK
;
403 if (smum_send_msg_to_smc_with_parameter(
404 hwmgr
->smumgr
, msg
, value
))
408 if (PP_STATE_SUPPORT_LS
& *msg_id
) {
409 msg
= (*msg_id
& PP_STATE_MASK
) & PP_STATE_LS
?
410 PPSMC_MSG_EnableClockGatingFeature
:
411 PPSMC_MSG_DisableClockGatingFeature
;
412 value
= CG_SYS_HDP_MGLS_MASK
;
414 if (smum_send_msg_to_smc_with_parameter(
415 hwmgr
->smumgr
, msg
, value
))
420 case PP_BLOCK_SYS_SDMA
:
421 if (PP_STATE_SUPPORT_CG
& *msg_id
) {
422 msg
= ((*msg_id
& PP_STATE_MASK
) & PP_STATE_CG
) ?
423 PPSMC_MSG_EnableClockGatingFeature
:
424 PPSMC_MSG_DisableClockGatingFeature
;
425 value
= CG_SYS_SDMA_MGCG_MASK
;
427 if (smum_send_msg_to_smc_with_parameter(
428 hwmgr
->smumgr
, msg
, value
))
432 if (PP_STATE_SUPPORT_LS
& *msg_id
) {
433 msg
= (*msg_id
& PP_STATE_MASK
) & PP_STATE_LS
?
434 PPSMC_MSG_EnableClockGatingFeature
:
435 PPSMC_MSG_DisableClockGatingFeature
;
436 value
= CG_SYS_SDMA_MGLS_MASK
;
438 if (smum_send_msg_to_smc_with_parameter(
439 hwmgr
->smumgr
, msg
, value
))
444 case PP_BLOCK_SYS_ROM
:
445 if (PP_STATE_SUPPORT_CG
& *msg_id
) {
446 msg
= ((*msg_id
& PP_STATE_MASK
) & PP_STATE_CG
) ?
447 PPSMC_MSG_EnableClockGatingFeature
:
448 PPSMC_MSG_DisableClockGatingFeature
;
449 value
= CG_SYS_ROM_MASK
;
451 if (smum_send_msg_to_smc_with_parameter(
452 hwmgr
->smumgr
, msg
, value
))
471 /* This function is for Polaris11 only for now,
472 * Powerplay will only control the static per CU Power Gating.
473 * Dynamic per CU Power Gating will be done in gfx.
475 int smu7_enable_per_cu_power_gating(struct pp_hwmgr
*hwmgr
, bool enable
)
477 struct cgs_system_info sys_info
= {0};
481 sys_info
.size
= sizeof(struct cgs_system_info
);
482 sys_info
.info_id
= CGS_SYSTEM_INFO_GFX_CU_INFO
;
484 result
= cgs_query_system_info(hwmgr
->device
, &sys_info
);
489 active_cus
= sys_info
.value
;
492 return smum_send_msg_to_smc_with_parameter(hwmgr
->smumgr
,
493 PPSMC_MSG_GFX_CU_PG_ENABLE
, active_cus
);
495 return smum_send_msg_to_smc(hwmgr
->smumgr
,
496 PPSMC_MSG_GFX_CU_PG_DISABLE
);