linux/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_clockpowergating.c
<<
>>
Prefs
   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
  28static 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
  35static 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
  42static 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
  49static 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
  56static 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
  63static 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
  70int 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
  78static 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
  94static 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
 102static 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
 110static 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
 119static 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
 128int 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
 143int 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_CG_STATE_UNGATE);
 166                smu7_update_uvd_dpm(hwmgr, false);
 167        }
 168
 169        return 0;
 170}
 171
 172int 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
 200int 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
 220int 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 */
 475int 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