Home | History | Annotate | Line # | Download | only in hwmgr
      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 
     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 
     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 
     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 
     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 
     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 
     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 
     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 
     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 
    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 
    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 
    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 
    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  */
    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