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, 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, 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, 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,
  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,
  84                                        PPSMC_MSG_UVDPowerON, 1);
  85                } else {
  86                        return smum_send_msg_to_smc_with_parameter(hwmgr,
  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,
  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,
 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,
 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,
 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
 143void 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}
 170
 171void smu7_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate)
 172{
 173        struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
 174
 175        data->vce_power_gated = bgate;
 176
 177        if (bgate) {
 178                cgs_set_powergating_state(hwmgr->device,
 179                                                AMD_IP_BLOCK_TYPE_VCE,
 180                                                AMD_PG_STATE_GATE);
 181                cgs_set_clockgating_state(hwmgr->device,
 182                                AMD_IP_BLOCK_TYPE_VCE,
 183                                AMD_CG_STATE_GATE);
 184                smu7_update_vce_dpm(hwmgr, true);
 185                smu7_powerdown_vce(hwmgr);
 186        } else {
 187                smu7_powerup_vce(hwmgr);
 188                cgs_set_clockgating_state(hwmgr->device,
 189                                AMD_IP_BLOCK_TYPE_VCE,
 190                                AMD_CG_STATE_UNGATE);
 191                cgs_set_powergating_state(hwmgr->device,
 192                                                AMD_IP_BLOCK_TYPE_VCE,
 193                                                AMD_PG_STATE_UNGATE);
 194                smu7_update_vce_dpm(hwmgr, false);
 195        }
 196}
 197
 198int smu7_powergate_samu(struct pp_hwmgr *hwmgr, bool bgate)
 199{
 200        struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
 201
 202        if (data->samu_power_gated == bgate)
 203                return 0;
 204
 205        data->samu_power_gated = bgate;
 206
 207        if (bgate) {
 208                smu7_update_samu_dpm(hwmgr, true);
 209                smu7_powerdown_samu(hwmgr);
 210        } else {
 211                smu7_powerup_samu(hwmgr);
 212                smu7_update_samu_dpm(hwmgr, false);
 213        }
 214
 215        return 0;
 216}
 217
 218int smu7_update_clock_gatings(struct pp_hwmgr *hwmgr,
 219                                        const uint32_t *msg_id)
 220{
 221        PPSMC_Msg msg;
 222        uint32_t value;
 223
 224        if (!(hwmgr->feature_mask & PP_ENABLE_GFX_CG_THRU_SMU))
 225                return 0;
 226
 227        switch ((*msg_id & PP_GROUP_MASK) >> PP_GROUP_SHIFT) {
 228        case PP_GROUP_GFX:
 229                switch ((*msg_id & PP_BLOCK_MASK) >> PP_BLOCK_SHIFT) {
 230                case PP_BLOCK_GFX_CG:
 231                        if (PP_STATE_SUPPORT_CG & *msg_id) {
 232                                msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
 233                                                PPSMC_MSG_EnableClockGatingFeature :
 234                                                PPSMC_MSG_DisableClockGatingFeature;
 235                                value = CG_GFX_CGCG_MASK;
 236
 237                                if (smum_send_msg_to_smc_with_parameter(
 238                                                hwmgr, msg, value))
 239                                        return -EINVAL;
 240                        }
 241                        if (PP_STATE_SUPPORT_LS & *msg_id) {
 242                                msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS
 243                                        ? PPSMC_MSG_EnableClockGatingFeature
 244                                        : PPSMC_MSG_DisableClockGatingFeature;
 245                                value = CG_GFX_CGLS_MASK;
 246
 247                                if (smum_send_msg_to_smc_with_parameter(
 248                                                hwmgr, msg, value))
 249                                        return -EINVAL;
 250                        }
 251                        break;
 252
 253                case PP_BLOCK_GFX_3D:
 254                        if (PP_STATE_SUPPORT_CG & *msg_id) {
 255                                msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
 256                                                PPSMC_MSG_EnableClockGatingFeature :
 257                                                PPSMC_MSG_DisableClockGatingFeature;
 258                                value = CG_GFX_3DCG_MASK;
 259
 260                                if (smum_send_msg_to_smc_with_parameter(
 261                                                hwmgr, msg, value))
 262                                        return -EINVAL;
 263                        }
 264
 265                        if  (PP_STATE_SUPPORT_LS & *msg_id) {
 266                                msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
 267                                                PPSMC_MSG_EnableClockGatingFeature :
 268                                                PPSMC_MSG_DisableClockGatingFeature;
 269                                value = CG_GFX_3DLS_MASK;
 270
 271                                if (smum_send_msg_to_smc_with_parameter(
 272                                                hwmgr, msg, value))
 273                                        return -EINVAL;
 274                        }
 275                        break;
 276
 277                case PP_BLOCK_GFX_RLC:
 278                        if (PP_STATE_SUPPORT_LS & *msg_id) {
 279                                msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
 280                                                PPSMC_MSG_EnableClockGatingFeature :
 281                                                PPSMC_MSG_DisableClockGatingFeature;
 282                                value = CG_GFX_RLC_LS_MASK;
 283
 284                                if (smum_send_msg_to_smc_with_parameter(
 285                                                hwmgr, msg, value))
 286                                        return -EINVAL;
 287                        }
 288                        break;
 289
 290                case PP_BLOCK_GFX_CP:
 291                        if (PP_STATE_SUPPORT_LS & *msg_id) {
 292                                msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
 293                                                PPSMC_MSG_EnableClockGatingFeature :
 294                                                PPSMC_MSG_DisableClockGatingFeature;
 295                                value = CG_GFX_CP_LS_MASK;
 296
 297                                if (smum_send_msg_to_smc_with_parameter(
 298                                                hwmgr, msg, value))
 299                                        return -EINVAL;
 300                        }
 301                        break;
 302
 303                case PP_BLOCK_GFX_MG:
 304                        if (PP_STATE_SUPPORT_CG & *msg_id) {
 305                                msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
 306                                                PPSMC_MSG_EnableClockGatingFeature :
 307                                                PPSMC_MSG_DisableClockGatingFeature;
 308                                value = (CG_CPF_MGCG_MASK | CG_RLC_MGCG_MASK |
 309                                                CG_GFX_OTHERS_MGCG_MASK);
 310
 311                                if (smum_send_msg_to_smc_with_parameter(
 312                                                hwmgr, msg, value))
 313                                        return -EINVAL;
 314                        }
 315                        break;
 316
 317                default:
 318                        return -EINVAL;
 319                }
 320                break;
 321
 322        case PP_GROUP_SYS:
 323                switch ((*msg_id & PP_BLOCK_MASK) >> PP_BLOCK_SHIFT) {
 324                case PP_BLOCK_SYS_BIF:
 325                        if (PP_STATE_SUPPORT_CG & *msg_id) {
 326                                msg = (*msg_id & PP_STATE_MASK) & PP_STATE_CG ?
 327                                                PPSMC_MSG_EnableClockGatingFeature :
 328                                                PPSMC_MSG_DisableClockGatingFeature;
 329                                value = CG_SYS_BIF_MGCG_MASK;
 330
 331                                if (smum_send_msg_to_smc_with_parameter(
 332                                                hwmgr, msg, value))
 333                                        return -EINVAL;
 334                        }
 335                        if  (PP_STATE_SUPPORT_LS & *msg_id) {
 336                                msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
 337                                                PPSMC_MSG_EnableClockGatingFeature :
 338                                                PPSMC_MSG_DisableClockGatingFeature;
 339                                value = CG_SYS_BIF_MGLS_MASK;
 340
 341                                if (smum_send_msg_to_smc_with_parameter(
 342                                                hwmgr, msg, value))
 343                                        return -EINVAL;
 344                        }
 345                        break;
 346
 347                case PP_BLOCK_SYS_MC:
 348                        if (PP_STATE_SUPPORT_CG & *msg_id) {
 349                                msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
 350                                                PPSMC_MSG_EnableClockGatingFeature :
 351                                                PPSMC_MSG_DisableClockGatingFeature;
 352                                value = CG_SYS_MC_MGCG_MASK;
 353
 354                                if (smum_send_msg_to_smc_with_parameter(
 355                                                hwmgr, msg, value))
 356                                        return -EINVAL;
 357                        }
 358
 359                        if (PP_STATE_SUPPORT_LS & *msg_id) {
 360                                msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
 361                                                PPSMC_MSG_EnableClockGatingFeature :
 362                                                PPSMC_MSG_DisableClockGatingFeature;
 363                                value = CG_SYS_MC_MGLS_MASK;
 364
 365                                if (smum_send_msg_to_smc_with_parameter(
 366                                                hwmgr, msg, value))
 367                                        return -EINVAL;
 368                        }
 369                        break;
 370
 371                case PP_BLOCK_SYS_DRM:
 372                        if (PP_STATE_SUPPORT_CG & *msg_id) {
 373                                msg = (*msg_id & PP_STATE_MASK) & PP_STATE_CG ?
 374                                                PPSMC_MSG_EnableClockGatingFeature :
 375                                                PPSMC_MSG_DisableClockGatingFeature;
 376                                value = CG_SYS_DRM_MGCG_MASK;
 377
 378                                if (smum_send_msg_to_smc_with_parameter(
 379                                                hwmgr, msg, value))
 380                                        return -EINVAL;
 381                        }
 382                        if (PP_STATE_SUPPORT_LS & *msg_id) {
 383                                msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
 384                                                PPSMC_MSG_EnableClockGatingFeature :
 385                                                PPSMC_MSG_DisableClockGatingFeature;
 386                                value = CG_SYS_DRM_MGLS_MASK;
 387
 388                                if (smum_send_msg_to_smc_with_parameter(
 389                                                hwmgr, msg, value))
 390                                        return -EINVAL;
 391                        }
 392                        break;
 393
 394                case PP_BLOCK_SYS_HDP:
 395                        if (PP_STATE_SUPPORT_CG & *msg_id) {
 396                                msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
 397                                                PPSMC_MSG_EnableClockGatingFeature :
 398                                                PPSMC_MSG_DisableClockGatingFeature;
 399                                value = CG_SYS_HDP_MGCG_MASK;
 400
 401                                if (smum_send_msg_to_smc_with_parameter(
 402                                                hwmgr, msg, value))
 403                                        return -EINVAL;
 404                        }
 405
 406                        if (PP_STATE_SUPPORT_LS & *msg_id) {
 407                                msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
 408                                                PPSMC_MSG_EnableClockGatingFeature :
 409                                                PPSMC_MSG_DisableClockGatingFeature;
 410                                value = CG_SYS_HDP_MGLS_MASK;
 411
 412                                if (smum_send_msg_to_smc_with_parameter(
 413                                                hwmgr, msg, value))
 414                                        return -EINVAL;
 415                        }
 416                        break;
 417
 418                case PP_BLOCK_SYS_SDMA:
 419                        if (PP_STATE_SUPPORT_CG & *msg_id) {
 420                                msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
 421                                                PPSMC_MSG_EnableClockGatingFeature :
 422                                                PPSMC_MSG_DisableClockGatingFeature;
 423                                value = CG_SYS_SDMA_MGCG_MASK;
 424
 425                                if (smum_send_msg_to_smc_with_parameter(
 426                                                hwmgr, msg, value))
 427                                        return -EINVAL;
 428                        }
 429
 430                        if (PP_STATE_SUPPORT_LS & *msg_id) {
 431                                msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ?
 432                                                PPSMC_MSG_EnableClockGatingFeature :
 433                                                PPSMC_MSG_DisableClockGatingFeature;
 434                                value = CG_SYS_SDMA_MGLS_MASK;
 435
 436                                if (smum_send_msg_to_smc_with_parameter(
 437                                                hwmgr, msg, value))
 438                                        return -EINVAL;
 439                        }
 440                        break;
 441
 442                case PP_BLOCK_SYS_ROM:
 443                        if (PP_STATE_SUPPORT_CG & *msg_id) {
 444                                msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ?
 445                                                PPSMC_MSG_EnableClockGatingFeature :
 446                                                PPSMC_MSG_DisableClockGatingFeature;
 447                                value = CG_SYS_ROM_MASK;
 448
 449                                if (smum_send_msg_to_smc_with_parameter(
 450                                                hwmgr, msg, value))
 451                                        return -EINVAL;
 452                        }
 453                        break;
 454
 455                default:
 456                        return -EINVAL;
 457
 458                }
 459                break;
 460
 461        default:
 462                return -EINVAL;
 463
 464        }
 465
 466        return 0;
 467}
 468
 469/* This function is for Polaris11 only for now,
 470 * Powerplay will only control the static per CU Power Gating.
 471 * Dynamic per CU Power Gating will be done in gfx.
 472 */
 473int smu7_enable_per_cu_power_gating(struct pp_hwmgr *hwmgr, bool enable)
 474{
 475        struct amdgpu_device *adev = hwmgr->adev;
 476
 477        if (enable)
 478                return smum_send_msg_to_smc_with_parameter(hwmgr,
 479                                        PPSMC_MSG_GFX_CU_PG_ENABLE,
 480                                        adev->gfx.cu_info.number);
 481        else
 482                return smum_send_msg_to_smc(hwmgr,
 483                                PPSMC_MSG_GFX_CU_PG_DISABLE);
 484}
 485