• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016 Advanced Micro Devices, Inc.
3  *
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:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
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.
21  *
22  */
23 
24 #include "smu7_hwmgr.h"
25 #include "smu7_clockpowergating.h"
26 #include "smu7_common.h"
27 
smu7_enable_disable_uvd_dpm(struct pp_hwmgr * hwmgr,bool enable)28 static int smu7_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable)
29 {
30 	return smum_send_msg_to_smc(hwmgr->smumgr, enable ?
31 			PPSMC_MSG_UVDDPM_Enable :
32 			PPSMC_MSG_UVDDPM_Disable);
33 }
34 
smu7_enable_disable_vce_dpm(struct pp_hwmgr * hwmgr,bool enable)35 static int smu7_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable)
36 {
37 	return smum_send_msg_to_smc(hwmgr->smumgr, enable ?
38 			PPSMC_MSG_VCEDPM_Enable :
39 			PPSMC_MSG_VCEDPM_Disable);
40 }
41 
smu7_enable_disable_samu_dpm(struct pp_hwmgr * hwmgr,bool enable)42 static int smu7_enable_disable_samu_dpm(struct pp_hwmgr *hwmgr, bool enable)
43 {
44 	return smum_send_msg_to_smc(hwmgr->smumgr, enable ?
45 			PPSMC_MSG_SAMUDPM_Enable :
46 			PPSMC_MSG_SAMUDPM_Disable);
47 }
48 
smu7_update_uvd_dpm(struct pp_hwmgr * hwmgr,bool bgate)49 static int smu7_update_uvd_dpm(struct pp_hwmgr *hwmgr, bool bgate)
50 {
51 	if (!bgate)
52 		smum_update_smc_table(hwmgr, SMU_UVD_TABLE);
53 	return smu7_enable_disable_uvd_dpm(hwmgr, !bgate);
54 }
55 
smu7_update_vce_dpm(struct pp_hwmgr * hwmgr,bool bgate)56 static int smu7_update_vce_dpm(struct pp_hwmgr *hwmgr, bool bgate)
57 {
58 	if (!bgate)
59 		smum_update_smc_table(hwmgr, SMU_VCE_TABLE);
60 	return smu7_enable_disable_vce_dpm(hwmgr, !bgate);
61 }
62 
smu7_update_samu_dpm(struct pp_hwmgr * hwmgr,bool bgate)63 static int smu7_update_samu_dpm(struct pp_hwmgr *hwmgr, bool bgate)
64 {
65 	if (!bgate)
66 		smum_update_smc_table(hwmgr, SMU_SAMU_TABLE);
67 	return smu7_enable_disable_samu_dpm(hwmgr, !bgate);
68 }
69 
smu7_powerdown_uvd(struct pp_hwmgr * hwmgr)70 int smu7_powerdown_uvd(struct pp_hwmgr *hwmgr)
71 {
72 	if (phm_cf_want_uvd_power_gating(hwmgr))
73 		return smum_send_msg_to_smc(hwmgr->smumgr,
74 				PPSMC_MSG_UVDPowerOFF);
75 	return 0;
76 }
77 
smu7_powerup_uvd(struct pp_hwmgr * hwmgr)78 static int smu7_powerup_uvd(struct pp_hwmgr *hwmgr)
79 {
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);
85 		} else {
86 			return smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
87 					PPSMC_MSG_UVDPowerON, 0);
88 		}
89 	}
90 
91 	return 0;
92 }
93 
smu7_powerdown_vce(struct pp_hwmgr * hwmgr)94 static int smu7_powerdown_vce(struct pp_hwmgr *hwmgr)
95 {
96 	if (phm_cf_want_vce_power_gating(hwmgr))
97 		return smum_send_msg_to_smc(hwmgr->smumgr,
98 				PPSMC_MSG_VCEPowerOFF);
99 	return 0;
100 }
101 
smu7_powerup_vce(struct pp_hwmgr * hwmgr)102 static int smu7_powerup_vce(struct pp_hwmgr *hwmgr)
103 {
104 	if (phm_cf_want_vce_power_gating(hwmgr))
105 		return smum_send_msg_to_smc(hwmgr->smumgr,
106 				PPSMC_MSG_VCEPowerON);
107 	return 0;
108 }
109 
smu7_powerdown_samu(struct pp_hwmgr * hwmgr)110 static int smu7_powerdown_samu(struct pp_hwmgr *hwmgr)
111 {
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);
116 	return 0;
117 }
118 
smu7_powerup_samu(struct pp_hwmgr * hwmgr)119 static int smu7_powerup_samu(struct pp_hwmgr *hwmgr)
120 {
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);
125 	return 0;
126 }
127 
smu7_disable_clock_power_gating(struct pp_hwmgr * hwmgr)128 int smu7_disable_clock_power_gating(struct pp_hwmgr *hwmgr)
129 {
130 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
131 
132 	data->uvd_power_gated = false;
133 	data->vce_power_gated = false;
134 	data->samu_power_gated = false;
135 
136 	smu7_powerup_uvd(hwmgr);
137 	smu7_powerup_vce(hwmgr);
138 	smu7_powerup_samu(hwmgr);
139 
140 	return 0;
141 }
142 
smu7_powergate_uvd(struct pp_hwmgr * hwmgr,bool bgate)143 int smu7_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate)
144 {
145 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
146 
147 	data->uvd_power_gated = bgate;
148 
149 	if (bgate) {
150 		cgs_set_powergating_state(hwmgr->device,
151 						AMD_IP_BLOCK_TYPE_UVD,
152 						AMD_PG_STATE_GATE);
153 		cgs_set_clockgating_state(hwmgr->device,
154 				AMD_IP_BLOCK_TYPE_UVD,
155 				AMD_CG_STATE_GATE);
156 		smu7_update_uvd_dpm(hwmgr, true);
157 		smu7_powerdown_uvd(hwmgr);
158 	} else {
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_PG_STATE_UNGATE);
166 		smu7_update_uvd_dpm(hwmgr, false);
167 	}
168 
169 	return 0;
170 }
171 
smu7_powergate_vce(struct pp_hwmgr * hwmgr,bool bgate)172 int smu7_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate)
173 {
174 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
175 
176 	data->vce_power_gated = bgate;
177 
178 	if (bgate) {
179 		cgs_set_powergating_state(hwmgr->device,
180 						AMD_IP_BLOCK_TYPE_VCE,
181 						AMD_PG_STATE_GATE);
182 		cgs_set_clockgating_state(hwmgr->device,
183 				AMD_IP_BLOCK_TYPE_VCE,
184 				AMD_CG_STATE_GATE);
185 		smu7_update_vce_dpm(hwmgr, true);
186 		smu7_powerdown_vce(hwmgr);
187 	} else {
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);
196 	}
197 	return 0;
198 }
199 
smu7_powergate_samu(struct pp_hwmgr * hwmgr,bool bgate)200 int smu7_powergate_samu(struct pp_hwmgr *hwmgr, bool bgate)
201 {
202 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
203 
204 	if (data->samu_power_gated == bgate)
205 		return 0;
206 
207 	data->samu_power_gated = bgate;
208 
209 	if (bgate) {
210 		smu7_update_samu_dpm(hwmgr, true);
211 		smu7_powerdown_samu(hwmgr);
212 	} else {
213 		smu7_powerup_samu(hwmgr);
214 		smu7_update_samu_dpm(hwmgr, false);
215 	}
216 
217 	return 0;
218 }
219 
smu7_update_clock_gatings(struct pp_hwmgr * hwmgr,const uint32_t * msg_id)220 int smu7_update_clock_gatings(struct pp_hwmgr *hwmgr,
221 					const uint32_t *msg_id)
222 {
223 	PPSMC_Msg msg;
224 	uint32_t value;
225 
226 	if (!(hwmgr->feature_mask & PP_ENABLE_GFX_CG_THRU_SMU))
227 		return 0;
228 
229 	switch ((*msg_id & PP_GROUP_MASK) >> PP_GROUP_SHIFT) {
230 	case PP_GROUP_GFX:
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;
238 
239 				if (smum_send_msg_to_smc_with_parameter(
240 						hwmgr->smumgr, msg, value))
241 					return -EINVAL;
242 			}
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;
248 
249 				if (smum_send_msg_to_smc_with_parameter(
250 						hwmgr->smumgr, msg, value))
251 					return -EINVAL;
252 			}
253 			break;
254 
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;
261 
262 				if (smum_send_msg_to_smc_with_parameter(
263 						hwmgr->smumgr, msg, value))
264 					return -EINVAL;
265 			}
266 
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;
272 
273 				if (smum_send_msg_to_smc_with_parameter(
274 						hwmgr->smumgr, msg, value))
275 					return -EINVAL;
276 			}
277 			break;
278 
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;
285 
286 				if (smum_send_msg_to_smc_with_parameter(
287 						hwmgr->smumgr, msg, value))
288 					return -EINVAL;
289 			}
290 			break;
291 
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;
298 
299 				if (smum_send_msg_to_smc_with_parameter(
300 						hwmgr->smumgr, msg, value))
301 					return -EINVAL;
302 			}
303 			break;
304 
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);
312 
313 				if (smum_send_msg_to_smc_with_parameter(
314 						hwmgr->smumgr, msg, value))
315 					return -EINVAL;
316 			}
317 			break;
318 
319 		default:
320 			return -EINVAL;
321 		}
322 		break;
323 
324 	case PP_GROUP_SYS:
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;
332 
333 				if (smum_send_msg_to_smc_with_parameter(
334 						hwmgr->smumgr, msg, value))
335 					return -EINVAL;
336 			}
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;
342 
343 				if (smum_send_msg_to_smc_with_parameter(
344 						hwmgr->smumgr, msg, value))
345 					return -EINVAL;
346 			}
347 			break;
348 
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;
355 
356 				if (smum_send_msg_to_smc_with_parameter(
357 						hwmgr->smumgr, msg, value))
358 					return -EINVAL;
359 			}
360 
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;
366 
367 				if (smum_send_msg_to_smc_with_parameter(
368 						hwmgr->smumgr, msg, value))
369 					return -EINVAL;
370 			}
371 			break;
372 
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;
379 
380 				if (smum_send_msg_to_smc_with_parameter(
381 						hwmgr->smumgr, msg, value))
382 					return -EINVAL;
383 			}
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;
389 
390 				if (smum_send_msg_to_smc_with_parameter(
391 						hwmgr->smumgr, msg, value))
392 					return -EINVAL;
393 			}
394 			break;
395 
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;
402 
403 				if (smum_send_msg_to_smc_with_parameter(
404 						hwmgr->smumgr, msg, value))
405 					return -EINVAL;
406 			}
407 
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;
413 
414 				if (smum_send_msg_to_smc_with_parameter(
415 						hwmgr->smumgr, msg, value))
416 					return -EINVAL;
417 			}
418 			break;
419 
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;
426 
427 				if (smum_send_msg_to_smc_with_parameter(
428 						hwmgr->smumgr, msg, value))
429 					return -EINVAL;
430 			}
431 
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;
437 
438 				if (smum_send_msg_to_smc_with_parameter(
439 						hwmgr->smumgr, msg, value))
440 					return -EINVAL;
441 			}
442 			break;
443 
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;
450 
451 				if (smum_send_msg_to_smc_with_parameter(
452 						hwmgr->smumgr, msg, value))
453 					return -EINVAL;
454 			}
455 			break;
456 
457 		default:
458 			return -EINVAL;
459 
460 		}
461 		break;
462 
463 	default:
464 		return -EINVAL;
465 
466 	}
467 
468 	return 0;
469 }
470 
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.
474  */
smu7_enable_per_cu_power_gating(struct pp_hwmgr * hwmgr,bool enable)475 int smu7_enable_per_cu_power_gating(struct pp_hwmgr *hwmgr, bool enable)
476 {
477 	struct cgs_system_info sys_info = {0};
478 	uint32_t active_cus;
479 	int result;
480 
481 	sys_info.size = sizeof(struct cgs_system_info);
482 	sys_info.info_id = CGS_SYSTEM_INFO_GFX_CU_INFO;
483 
484 	result = cgs_query_system_info(hwmgr->device, &sys_info);
485 
486 	if (result)
487 		return -EINVAL;
488 
489 	active_cus = sys_info.value;
490 
491 	if (enable)
492 		return smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
493 				PPSMC_MSG_GFX_CU_PG_ENABLE, active_cus);
494 	else
495 		return smum_send_msg_to_smc(hwmgr->smumgr,
496 				PPSMC_MSG_GFX_CU_PG_DISABLE);
497 }
498