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