1 /* $NetBSD: amdgpu_smu7_clockpowergating.c,v 1.2 2021/12/18 23:45:26 riastradh Exp $ */
2
3 /*
4 * Copyright 2016 Advanced Micro Devices, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 *
24 */
25
26 #include <sys/cdefs.h>
27 __KERNEL_RCSID(0, "$NetBSD: amdgpu_smu7_clockpowergating.c,v 1.2 2021/12/18 23:45:26 riastradh Exp $");
28
29 #include "smu7_hwmgr.h"
30 #include "smu7_clockpowergating.h"
31 #include "smu7_common.h"
32
smu7_enable_disable_uvd_dpm(struct pp_hwmgr * hwmgr,bool enable)33 static int smu7_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable)
34 {
35 return smum_send_msg_to_smc(hwmgr, enable ?
36 PPSMC_MSG_UVDDPM_Enable :
37 PPSMC_MSG_UVDDPM_Disable);
38 }
39
smu7_enable_disable_vce_dpm(struct pp_hwmgr * hwmgr,bool enable)40 static int smu7_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable)
41 {
42 return smum_send_msg_to_smc(hwmgr, enable ?
43 PPSMC_MSG_VCEDPM_Enable :
44 PPSMC_MSG_VCEDPM_Disable);
45 }
46
smu7_update_uvd_dpm(struct pp_hwmgr * hwmgr,bool bgate)47 static int smu7_update_uvd_dpm(struct pp_hwmgr *hwmgr, bool bgate)
48 {
49 if (!bgate)
50 smum_update_smc_table(hwmgr, SMU_UVD_TABLE);
51 return smu7_enable_disable_uvd_dpm(hwmgr, !bgate);
52 }
53
smu7_update_vce_dpm(struct pp_hwmgr * hwmgr,bool bgate)54 static int smu7_update_vce_dpm(struct pp_hwmgr *hwmgr, bool bgate)
55 {
56 if (!bgate)
57 smum_update_smc_table(hwmgr, SMU_VCE_TABLE);
58 return smu7_enable_disable_vce_dpm(hwmgr, !bgate);
59 }
60
smu7_powerdown_uvd(struct pp_hwmgr * hwmgr)61 int smu7_powerdown_uvd(struct pp_hwmgr *hwmgr)
62 {
63 if (phm_cf_want_uvd_power_gating(hwmgr))
64 return smum_send_msg_to_smc(hwmgr,
65 PPSMC_MSG_UVDPowerOFF);
66 return 0;
67 }
68
smu7_powerup_uvd(struct pp_hwmgr * hwmgr)69 static int smu7_powerup_uvd(struct pp_hwmgr *hwmgr)
70 {
71 if (phm_cf_want_uvd_power_gating(hwmgr)) {
72 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
73 PHM_PlatformCaps_UVDDynamicPowerGating)) {
74 return smum_send_msg_to_smc_with_parameter(hwmgr,
75 PPSMC_MSG_UVDPowerON, 1);
76 } else {
77 return smum_send_msg_to_smc_with_parameter(hwmgr,
78 PPSMC_MSG_UVDPowerON, 0);
79 }
80 }
81
82 return 0;
83 }
84
smu7_powerdown_vce(struct pp_hwmgr * hwmgr)85 static int smu7_powerdown_vce(struct pp_hwmgr *hwmgr)
86 {
87 if (phm_cf_want_vce_power_gating(hwmgr))
88 return smum_send_msg_to_smc(hwmgr,
89 PPSMC_MSG_VCEPowerOFF);
90 return 0;
91 }
92
smu7_powerup_vce(struct pp_hwmgr * hwmgr)93 static int smu7_powerup_vce(struct pp_hwmgr *hwmgr)
94 {
95 if (phm_cf_want_vce_power_gating(hwmgr))
96 return smum_send_msg_to_smc(hwmgr,
97 PPSMC_MSG_VCEPowerON);
98 return 0;
99 }
100
smu7_disable_clock_power_gating(struct pp_hwmgr * hwmgr)101 int smu7_disable_clock_power_gating(struct pp_hwmgr *hwmgr)
102 {
103 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
104
105 data->uvd_power_gated = false;
106 data->vce_power_gated = false;
107
108 smu7_powerup_uvd(hwmgr);
109 smu7_powerup_vce(hwmgr);
110
111 return 0;
112 }
113
smu7_powergate_uvd(struct pp_hwmgr * hwmgr,bool bgate)114 void smu7_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate)
115 {
116 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
117
118 data->uvd_power_gated = bgate;
119
120 if (bgate) {
121 amdgpu_device_ip_set_powergating_state(hwmgr->adev,
122 AMD_IP_BLOCK_TYPE_UVD,
123 AMD_PG_STATE_GATE);
124 amdgpu_device_ip_set_clockgating_state(hwmgr->adev,
125 AMD_IP_BLOCK_TYPE_UVD,
126 AMD_CG_STATE_GATE);
127 smu7_update_uvd_dpm(hwmgr, true);
128 smu7_powerdown_uvd(hwmgr);
129 } else {
130 smu7_powerup_uvd(hwmgr);
131 amdgpu_device_ip_set_clockgating_state(hwmgr->adev,
132 AMD_IP_BLOCK_TYPE_UVD,
133 AMD_CG_STATE_UNGATE);
134 amdgpu_device_ip_set_powergating_state(hwmgr->adev,
135 AMD_IP_BLOCK_TYPE_UVD,
136 AMD_PG_STATE_UNGATE);
137 smu7_update_uvd_dpm(hwmgr, false);
138 }
139
140 }
141
smu7_powergate_vce(struct pp_hwmgr * hwmgr,bool bgate)142 void smu7_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate)
143 {
144 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
145
146 data->vce_power_gated = bgate;
147
148 if (bgate) {
149 amdgpu_device_ip_set_powergating_state(hwmgr->adev,
150 AMD_IP_BLOCK_TYPE_VCE,
151 AMD_PG_STATE_GATE);
152 amdgpu_device_ip_set_clockgating_state(hwmgr->adev,
153 AMD_IP_BLOCK_TYPE_VCE,
154 AMD_CG_STATE_GATE);
155 smu7_update_vce_dpm(hwmgr, true);
156 smu7_powerdown_vce(hwmgr);
157 } else {
158 smu7_powerup_vce(hwmgr);
159 amdgpu_device_ip_set_clockgating_state(hwmgr->adev,
160 AMD_IP_BLOCK_TYPE_VCE,
161 AMD_CG_STATE_UNGATE);
162 amdgpu_device_ip_set_powergating_state(hwmgr->adev,
163 AMD_IP_BLOCK_TYPE_VCE,
164 AMD_PG_STATE_UNGATE);
165 smu7_update_vce_dpm(hwmgr, false);
166 }
167 }
168
smu7_update_clock_gatings(struct pp_hwmgr * hwmgr,const uint32_t * msg_id)169 int smu7_update_clock_gatings(struct pp_hwmgr *hwmgr,
170 const uint32_t *msg_id)
171 {
172 PPSMC_Msg msg;
173 uint32_t value;
174
175 if (!(hwmgr->feature_mask & PP_ENABLE_GFX_CG_THRU_SMU))
176 return 0;
177
178 switch ((*msg_id & PP_GROUP_MASK) >> PP_GROUP_SHIFT) {
179 case PP_GROUP_GFX:
180 switch ((*msg_id & PP_BLOCK_MASK) >> PP_BLOCK_SHIFT) {
181 case PP_BLOCK_GFX_CG:
182 if (PP_STATE_SUPPORT_CG & *msg_id) {
183 msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
184 PPSMC_MSG_EnableClockGatingFeature :
185 PPSMC_MSG_DisableClockGatingFeature;
186 value = CG_GFX_CGCG_MASK;
187
188 if (smum_send_msg_to_smc_with_parameter(
189 hwmgr, msg, value))
190 return -EINVAL;
191 }
192 if (PP_STATE_SUPPORT_LS & *msg_id) {
193 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS
194 ? PPSMC_MSG_EnableClockGatingFeature
195 : PPSMC_MSG_DisableClockGatingFeature;
196 value = CG_GFX_CGLS_MASK;
197
198 if (smum_send_msg_to_smc_with_parameter(
199 hwmgr, msg, value))
200 return -EINVAL;
201 }
202 break;
203
204 case PP_BLOCK_GFX_3D:
205 if (PP_STATE_SUPPORT_CG & *msg_id) {
206 msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
207 PPSMC_MSG_EnableClockGatingFeature :
208 PPSMC_MSG_DisableClockGatingFeature;
209 value = CG_GFX_3DCG_MASK;
210
211 if (smum_send_msg_to_smc_with_parameter(
212 hwmgr, msg, value))
213 return -EINVAL;
214 }
215
216 if (PP_STATE_SUPPORT_LS & *msg_id) {
217 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
218 PPSMC_MSG_EnableClockGatingFeature :
219 PPSMC_MSG_DisableClockGatingFeature;
220 value = CG_GFX_3DLS_MASK;
221
222 if (smum_send_msg_to_smc_with_parameter(
223 hwmgr, msg, value))
224 return -EINVAL;
225 }
226 break;
227
228 case PP_BLOCK_GFX_RLC:
229 if (PP_STATE_SUPPORT_LS & *msg_id) {
230 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
231 PPSMC_MSG_EnableClockGatingFeature :
232 PPSMC_MSG_DisableClockGatingFeature;
233 value = CG_GFX_RLC_LS_MASK;
234
235 if (smum_send_msg_to_smc_with_parameter(
236 hwmgr, msg, value))
237 return -EINVAL;
238 }
239 break;
240
241 case PP_BLOCK_GFX_CP:
242 if (PP_STATE_SUPPORT_LS & *msg_id) {
243 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
244 PPSMC_MSG_EnableClockGatingFeature :
245 PPSMC_MSG_DisableClockGatingFeature;
246 value = CG_GFX_CP_LS_MASK;
247
248 if (smum_send_msg_to_smc_with_parameter(
249 hwmgr, msg, value))
250 return -EINVAL;
251 }
252 break;
253
254 case PP_BLOCK_GFX_MG:
255 if (PP_STATE_SUPPORT_CG & *msg_id) {
256 msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
257 PPSMC_MSG_EnableClockGatingFeature :
258 PPSMC_MSG_DisableClockGatingFeature;
259 value = (CG_CPF_MGCG_MASK | CG_RLC_MGCG_MASK |
260 CG_GFX_OTHERS_MGCG_MASK);
261
262 if (smum_send_msg_to_smc_with_parameter(
263 hwmgr, msg, value))
264 return -EINVAL;
265 }
266 break;
267
268 default:
269 return -EINVAL;
270 }
271 break;
272
273 case PP_GROUP_SYS:
274 switch ((*msg_id & PP_BLOCK_MASK) >> PP_BLOCK_SHIFT) {
275 case PP_BLOCK_SYS_BIF:
276 if (PP_STATE_SUPPORT_CG & *msg_id) {
277 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_CG ?
278 PPSMC_MSG_EnableClockGatingFeature :
279 PPSMC_MSG_DisableClockGatingFeature;
280 value = CG_SYS_BIF_MGCG_MASK;
281
282 if (smum_send_msg_to_smc_with_parameter(
283 hwmgr, msg, value))
284 return -EINVAL;
285 }
286 if (PP_STATE_SUPPORT_LS & *msg_id) {
287 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
288 PPSMC_MSG_EnableClockGatingFeature :
289 PPSMC_MSG_DisableClockGatingFeature;
290 value = CG_SYS_BIF_MGLS_MASK;
291
292 if (smum_send_msg_to_smc_with_parameter(
293 hwmgr, msg, value))
294 return -EINVAL;
295 }
296 break;
297
298 case PP_BLOCK_SYS_MC:
299 if (PP_STATE_SUPPORT_CG & *msg_id) {
300 msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
301 PPSMC_MSG_EnableClockGatingFeature :
302 PPSMC_MSG_DisableClockGatingFeature;
303 value = CG_SYS_MC_MGCG_MASK;
304
305 if (smum_send_msg_to_smc_with_parameter(
306 hwmgr, msg, value))
307 return -EINVAL;
308 }
309
310 if (PP_STATE_SUPPORT_LS & *msg_id) {
311 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
312 PPSMC_MSG_EnableClockGatingFeature :
313 PPSMC_MSG_DisableClockGatingFeature;
314 value = CG_SYS_MC_MGLS_MASK;
315
316 if (smum_send_msg_to_smc_with_parameter(
317 hwmgr, msg, value))
318 return -EINVAL;
319 }
320 break;
321
322 case PP_BLOCK_SYS_DRM:
323 if (PP_STATE_SUPPORT_CG & *msg_id) {
324 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_CG ?
325 PPSMC_MSG_EnableClockGatingFeature :
326 PPSMC_MSG_DisableClockGatingFeature;
327 value = CG_SYS_DRM_MGCG_MASK;
328
329 if (smum_send_msg_to_smc_with_parameter(
330 hwmgr, msg, value))
331 return -EINVAL;
332 }
333 if (PP_STATE_SUPPORT_LS & *msg_id) {
334 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
335 PPSMC_MSG_EnableClockGatingFeature :
336 PPSMC_MSG_DisableClockGatingFeature;
337 value = CG_SYS_DRM_MGLS_MASK;
338
339 if (smum_send_msg_to_smc_with_parameter(
340 hwmgr, msg, value))
341 return -EINVAL;
342 }
343 break;
344
345 case PP_BLOCK_SYS_HDP:
346 if (PP_STATE_SUPPORT_CG & *msg_id) {
347 msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
348 PPSMC_MSG_EnableClockGatingFeature :
349 PPSMC_MSG_DisableClockGatingFeature;
350 value = CG_SYS_HDP_MGCG_MASK;
351
352 if (smum_send_msg_to_smc_with_parameter(
353 hwmgr, msg, value))
354 return -EINVAL;
355 }
356
357 if (PP_STATE_SUPPORT_LS & *msg_id) {
358 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
359 PPSMC_MSG_EnableClockGatingFeature :
360 PPSMC_MSG_DisableClockGatingFeature;
361 value = CG_SYS_HDP_MGLS_MASK;
362
363 if (smum_send_msg_to_smc_with_parameter(
364 hwmgr, msg, value))
365 return -EINVAL;
366 }
367 break;
368
369 case PP_BLOCK_SYS_SDMA:
370 if (PP_STATE_SUPPORT_CG & *msg_id) {
371 msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
372 PPSMC_MSG_EnableClockGatingFeature :
373 PPSMC_MSG_DisableClockGatingFeature;
374 value = CG_SYS_SDMA_MGCG_MASK;
375
376 if (smum_send_msg_to_smc_with_parameter(
377 hwmgr, msg, value))
378 return -EINVAL;
379 }
380
381 if (PP_STATE_SUPPORT_LS & *msg_id) {
382 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
383 PPSMC_MSG_EnableClockGatingFeature :
384 PPSMC_MSG_DisableClockGatingFeature;
385 value = CG_SYS_SDMA_MGLS_MASK;
386
387 if (smum_send_msg_to_smc_with_parameter(
388 hwmgr, msg, value))
389 return -EINVAL;
390 }
391 break;
392
393 case PP_BLOCK_SYS_ROM:
394 if (PP_STATE_SUPPORT_CG & *msg_id) {
395 msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
396 PPSMC_MSG_EnableClockGatingFeature :
397 PPSMC_MSG_DisableClockGatingFeature;
398 value = CG_SYS_ROM_MASK;
399
400 if (smum_send_msg_to_smc_with_parameter(
401 hwmgr, msg, value))
402 return -EINVAL;
403 }
404 break;
405
406 default:
407 return -EINVAL;
408
409 }
410 break;
411
412 default:
413 return -EINVAL;
414
415 }
416
417 return 0;
418 }
419
420 /* This function is for Polaris11 only for now,
421 * Powerplay will only control the static per CU Power Gating.
422 * Dynamic per CU Power Gating will be done in gfx.
423 */
smu7_powergate_gfx(struct pp_hwmgr * hwmgr,bool enable)424 int smu7_powergate_gfx(struct pp_hwmgr *hwmgr, bool enable)
425 {
426 struct amdgpu_device *adev = hwmgr->adev;
427
428 if (enable)
429 return smum_send_msg_to_smc_with_parameter(hwmgr,
430 PPSMC_MSG_GFX_CU_PG_ENABLE,
431 adev->gfx.cu_info.number);
432 else
433 return smum_send_msg_to_smc(hwmgr,
434 PPSMC_MSG_GFX_CU_PG_DISABLE);
435 }
436