linux/drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.c
<<
>>
Prefs
   1/*
   2 * Copyright 2021 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#define SWSMU_CODE_LAYER_L2
  25
  26#include "amdgpu.h"
  27#include "amdgpu_smu.h"
  28#include "smu_v11_0.h"
  29#include "smu11_driver_if_cyan_skillfish.h"
  30#include "cyan_skillfish_ppt.h"
  31#include "smu_v11_8_ppsmc.h"
  32#include "smu_v11_8_pmfw.h"
  33#include "smu_cmn.h"
  34#include "soc15_common.h"
  35
  36/*
  37 * DO NOT use these for err/warn/info/debug messages.
  38 * Use dev_err, dev_warn, dev_info and dev_dbg instead.
  39 * They are more MGPU friendly.
  40 */
  41
  42#undef pr_err
  43#undef pr_warn
  44#undef pr_info
  45#undef pr_debug
  46
  47/* unit: MHz */
  48#define CYAN_SKILLFISH_SCLK_MIN                 1000
  49#define CYAN_SKILLFISH_SCLK_MAX                 2000
  50#define CYAN_SKILLFISH_SCLK_DEFAULT                     1800
  51
  52/* unit: mV */
  53#define CYAN_SKILLFISH_VDDC_MIN                 700
  54#define CYAN_SKILLFISH_VDDC_MAX                 1129
  55#define CYAN_SKILLFISH_VDDC_MAGIC                       5118 // 0x13fe
  56
  57static struct gfx_user_settings {
  58        uint32_t sclk;
  59        uint32_t vddc;
  60} cyan_skillfish_user_settings;
  61
  62#define FEATURE_MASK(feature) (1ULL << feature)
  63#define SMC_DPM_FEATURE ( \
  64        FEATURE_MASK(FEATURE_FCLK_DPM_BIT)      |       \
  65        FEATURE_MASK(FEATURE_SOC_DPM_BIT)       |       \
  66        FEATURE_MASK(FEATURE_GFX_DPM_BIT))
  67
  68static struct cmn2asic_msg_mapping cyan_skillfish_message_map[SMU_MSG_MAX_COUNT] = {
  69        MSG_MAP(TestMessage,                    PPSMC_MSG_TestMessage,                  0),
  70        MSG_MAP(GetSmuVersion,                  PPSMC_MSG_GetSmuVersion,                0),
  71        MSG_MAP(GetDriverIfVersion,             PPSMC_MSG_GetDriverIfVersion,           0),
  72        MSG_MAP(SetDriverDramAddrHigh,          PPSMC_MSG_SetDriverTableDramAddrHigh,   0),
  73        MSG_MAP(SetDriverDramAddrLow,           PPSMC_MSG_SetDriverTableDramAddrLow,    0),
  74        MSG_MAP(TransferTableSmu2Dram,          PPSMC_MSG_TransferTableSmu2Dram,        0),
  75        MSG_MAP(TransferTableDram2Smu,          PPSMC_MSG_TransferTableDram2Smu,        0),
  76        MSG_MAP(GetEnabledSmuFeatures,          PPSMC_MSG_GetEnabledSmuFeatures,        0),
  77        MSG_MAP(RequestGfxclk,                  PPSMC_MSG_RequestGfxclk,                0),
  78        MSG_MAP(ForceGfxVid,                    PPSMC_MSG_ForceGfxVid,                  0),
  79        MSG_MAP(UnforceGfxVid,                  PPSMC_MSG_UnforceGfxVid,                0),
  80};
  81
  82static struct cmn2asic_mapping cyan_skillfish_table_map[SMU_TABLE_COUNT] = {
  83        TAB_MAP_VALID(SMU_METRICS),
  84};
  85
  86static int cyan_skillfish_tables_init(struct smu_context *smu)
  87{
  88        struct smu_table_context *smu_table = &smu->smu_table;
  89        struct smu_table *tables = smu_table->tables;
  90
  91        SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS,
  92                                sizeof(SmuMetrics_t),
  93                                PAGE_SIZE,
  94                                AMDGPU_GEM_DOMAIN_VRAM);
  95
  96        smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL);
  97        if (!smu_table->metrics_table)
  98                goto err0_out;
  99
 100        smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v2_2);
 101        smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL);
 102        if (!smu_table->gpu_metrics_table)
 103                goto err1_out;
 104
 105        smu_table->metrics_time = 0;
 106
 107        return 0;
 108
 109err1_out:
 110        smu_table->gpu_metrics_table_size = 0;
 111        kfree(smu_table->metrics_table);
 112err0_out:
 113        return -ENOMEM;
 114}
 115
 116static int cyan_skillfish_init_smc_tables(struct smu_context *smu)
 117{
 118        int ret = 0;
 119
 120        ret = cyan_skillfish_tables_init(smu);
 121        if (ret)
 122                return ret;
 123
 124        return smu_v11_0_init_smc_tables(smu);
 125}
 126
 127static int cyan_skillfish_finit_smc_tables(struct smu_context *smu)
 128{
 129        struct smu_table_context *smu_table = &smu->smu_table;
 130
 131        kfree(smu_table->metrics_table);
 132        smu_table->metrics_table = NULL;
 133
 134        kfree(smu_table->gpu_metrics_table);
 135        smu_table->gpu_metrics_table = NULL;
 136        smu_table->gpu_metrics_table_size = 0;
 137
 138        smu_table->metrics_time = 0;
 139
 140        return 0;
 141}
 142
 143static int
 144cyan_skillfish_get_smu_metrics_data(struct smu_context *smu,
 145                                        MetricsMember_t member,
 146                                        uint32_t *value)
 147{
 148        struct smu_table_context *smu_table = &smu->smu_table;
 149        SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table;
 150        int ret = 0;
 151
 152        mutex_lock(&smu->metrics_lock);
 153
 154        ret = smu_cmn_get_metrics_table_locked(smu, NULL, false);
 155        if (ret) {
 156                mutex_unlock(&smu->metrics_lock);
 157                return ret;
 158        }
 159
 160        switch (member) {
 161        case METRICS_CURR_GFXCLK:
 162                *value = metrics->Current.GfxclkFrequency;
 163                break;
 164        case METRICS_CURR_SOCCLK:
 165                *value = metrics->Current.SocclkFrequency;
 166                break;
 167        case METRICS_CURR_VCLK:
 168                *value = metrics->Current.VclkFrequency;
 169                break;
 170        case METRICS_CURR_DCLK:
 171                *value = metrics->Current.DclkFrequency;
 172                break;
 173        case METRICS_CURR_UCLK:
 174                *value = metrics->Current.MemclkFrequency;
 175                break;
 176        case METRICS_AVERAGE_SOCKETPOWER:
 177                *value = (metrics->Current.CurrentSocketPower << 8) /
 178                                1000;
 179                break;
 180        case METRICS_TEMPERATURE_EDGE:
 181                *value = metrics->Current.GfxTemperature / 100 *
 182                                SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
 183                break;
 184        case METRICS_TEMPERATURE_HOTSPOT:
 185                *value = metrics->Current.SocTemperature / 100 *
 186                                SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
 187                break;
 188        case METRICS_VOLTAGE_VDDSOC:
 189                *value = metrics->Current.Voltage[0];
 190                break;
 191        case METRICS_VOLTAGE_VDDGFX:
 192                *value = metrics->Current.Voltage[1];
 193                break;
 194        case METRICS_THROTTLER_STATUS:
 195                *value = metrics->Current.ThrottlerStatus;
 196                break;
 197        default:
 198                *value = UINT_MAX;
 199                break;
 200        }
 201
 202        mutex_unlock(&smu->metrics_lock);
 203
 204        return ret;
 205}
 206
 207static int cyan_skillfish_read_sensor(struct smu_context *smu,
 208                                        enum amd_pp_sensors sensor,
 209                                        void *data,
 210                                        uint32_t *size)
 211{
 212        int ret = 0;
 213
 214        if (!data || !size)
 215                return -EINVAL;
 216
 217        mutex_lock(&smu->sensor_lock);
 218
 219        switch (sensor) {
 220        case AMDGPU_PP_SENSOR_GFX_SCLK:
 221                ret = cyan_skillfish_get_smu_metrics_data(smu,
 222                                                   METRICS_CURR_GFXCLK,
 223                                                   (uint32_t *)data);
 224                *(uint32_t *)data *= 100;
 225                *size = 4;
 226                break;
 227        case AMDGPU_PP_SENSOR_GFX_MCLK:
 228                ret = cyan_skillfish_get_smu_metrics_data(smu,
 229                                                   METRICS_CURR_UCLK,
 230                                                   (uint32_t *)data);
 231                *(uint32_t *)data *= 100;
 232                *size = 4;
 233                break;
 234        case AMDGPU_PP_SENSOR_GPU_POWER:
 235                ret = cyan_skillfish_get_smu_metrics_data(smu,
 236                                                   METRICS_AVERAGE_SOCKETPOWER,
 237                                                   (uint32_t *)data);
 238                *size = 4;
 239                break;
 240        case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
 241                ret = cyan_skillfish_get_smu_metrics_data(smu,
 242                                                   METRICS_TEMPERATURE_HOTSPOT,
 243                                                   (uint32_t *)data);
 244                *size = 4;
 245                break;
 246        case AMDGPU_PP_SENSOR_EDGE_TEMP:
 247                ret = cyan_skillfish_get_smu_metrics_data(smu,
 248                                                   METRICS_TEMPERATURE_EDGE,
 249                                                   (uint32_t *)data);
 250                *size = 4;
 251                break;
 252        case AMDGPU_PP_SENSOR_VDDNB:
 253                ret = cyan_skillfish_get_smu_metrics_data(smu,
 254                                                   METRICS_VOLTAGE_VDDSOC,
 255                                                   (uint32_t *)data);
 256                *size = 4;
 257                break;
 258        case AMDGPU_PP_SENSOR_VDDGFX:
 259                ret = cyan_skillfish_get_smu_metrics_data(smu,
 260                                                   METRICS_VOLTAGE_VDDGFX,
 261                                                   (uint32_t *)data);
 262                *size = 4;
 263                break;
 264        default:
 265                ret = -EOPNOTSUPP;
 266                break;
 267        }
 268
 269        mutex_unlock(&smu->sensor_lock);
 270
 271        return ret;
 272}
 273
 274static int cyan_skillfish_get_current_clk_freq(struct smu_context *smu,
 275                                                enum smu_clk_type clk_type,
 276                                                uint32_t *value)
 277{
 278        MetricsMember_t member_type;
 279
 280        switch (clk_type) {
 281        case SMU_GFXCLK:
 282        case SMU_SCLK:
 283                member_type = METRICS_CURR_GFXCLK;
 284                break;
 285        case SMU_FCLK:
 286        case SMU_MCLK:
 287                member_type = METRICS_CURR_UCLK;
 288                break;
 289        case SMU_SOCCLK:
 290                member_type = METRICS_CURR_SOCCLK;
 291                break;
 292        case SMU_VCLK:
 293                member_type = METRICS_CURR_VCLK;
 294                break;
 295        case SMU_DCLK:
 296                member_type = METRICS_CURR_DCLK;
 297                break;
 298        default:
 299                return -EINVAL;
 300        }
 301
 302        return cyan_skillfish_get_smu_metrics_data(smu, member_type, value);
 303}
 304
 305static int cyan_skillfish_print_clk_levels(struct smu_context *smu,
 306                                        enum smu_clk_type clk_type,
 307                                        char *buf)
 308{
 309        int ret = 0, size = 0;
 310        uint32_t cur_value = 0;
 311
 312        smu_cmn_get_sysfs_buf(&buf, &size);
 313
 314        switch (clk_type) {
 315        case SMU_OD_SCLK:
 316                ret  = cyan_skillfish_get_smu_metrics_data(smu, METRICS_CURR_GFXCLK, &cur_value);
 317                if (ret)
 318                        return ret;
 319                size += sysfs_emit_at(buf, size,"%s:\n", "OD_SCLK");
 320                size += sysfs_emit_at(buf, size, "0: %uMhz *\n", cur_value);
 321                break;
 322        case SMU_OD_VDDC_CURVE:
 323                ret  = cyan_skillfish_get_smu_metrics_data(smu, METRICS_VOLTAGE_VDDGFX, &cur_value);
 324                if (ret)
 325                        return ret;
 326                size += sysfs_emit_at(buf, size,"%s:\n", "OD_VDDC");
 327                size += sysfs_emit_at(buf, size, "0: %umV *\n", cur_value);
 328                break;
 329        case SMU_OD_RANGE:
 330                size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE");
 331                size += sysfs_emit_at(buf, size, "SCLK: %7uMhz %10uMhz\n",
 332                                                CYAN_SKILLFISH_SCLK_MIN, CYAN_SKILLFISH_SCLK_MAX);
 333                size += sysfs_emit_at(buf, size, "VDDC: %7umV  %10umV\n",
 334                                                CYAN_SKILLFISH_VDDC_MIN, CYAN_SKILLFISH_VDDC_MAX);
 335                break;
 336        case SMU_GFXCLK:
 337        case SMU_SCLK:
 338        case SMU_FCLK:
 339        case SMU_MCLK:
 340        case SMU_SOCCLK:
 341        case SMU_VCLK:
 342        case SMU_DCLK:
 343                ret = cyan_skillfish_get_current_clk_freq(smu, clk_type, &cur_value);
 344                if (ret)
 345                        return ret;
 346                size += sysfs_emit_at(buf, size, "0: %uMhz *\n", cur_value);
 347                break;
 348        default:
 349                dev_warn(smu->adev->dev, "Unsupported clock type\n");
 350                return ret;
 351        }
 352
 353        return size;
 354}
 355
 356static bool cyan_skillfish_is_dpm_running(struct smu_context *smu)
 357{
 358        struct amdgpu_device *adev = smu->adev;
 359        int ret = 0;
 360        uint32_t feature_mask[2];
 361        uint64_t feature_enabled;
 362
 363        /* we need to re-init after suspend so return false */
 364        if (adev->in_suspend)
 365                return false;
 366
 367        ret = smu_cmn_get_enabled_32_bits_mask(smu, feature_mask, 2);
 368
 369        if (ret)
 370                return false;
 371
 372        feature_enabled = (uint64_t)feature_mask[0] |
 373                                ((uint64_t)feature_mask[1] << 32);
 374
 375        return !!(feature_enabled & SMC_DPM_FEATURE);
 376}
 377
 378static ssize_t cyan_skillfish_get_gpu_metrics(struct smu_context *smu,
 379                                                void **table)
 380{
 381        struct smu_table_context *smu_table = &smu->smu_table;
 382        struct gpu_metrics_v2_2 *gpu_metrics =
 383                (struct gpu_metrics_v2_2 *)smu_table->gpu_metrics_table;
 384        SmuMetrics_t metrics;
 385        int i, ret = 0;
 386
 387        ret = smu_cmn_get_metrics_table(smu, &metrics, true);
 388        if (ret)
 389                return ret;
 390
 391        smu_cmn_init_soft_gpu_metrics(gpu_metrics, 2, 2);
 392
 393        gpu_metrics->temperature_gfx = metrics.Current.GfxTemperature;
 394        gpu_metrics->temperature_soc = metrics.Current.SocTemperature;
 395
 396        gpu_metrics->average_socket_power = metrics.Current.CurrentSocketPower;
 397        gpu_metrics->average_soc_power = metrics.Current.Power[0];
 398        gpu_metrics->average_gfx_power = metrics.Current.Power[1];
 399
 400        gpu_metrics->average_gfxclk_frequency = metrics.Average.GfxclkFrequency;
 401        gpu_metrics->average_socclk_frequency = metrics.Average.SocclkFrequency;
 402        gpu_metrics->average_uclk_frequency = metrics.Average.MemclkFrequency;
 403        gpu_metrics->average_fclk_frequency = metrics.Average.MemclkFrequency;
 404        gpu_metrics->average_vclk_frequency = metrics.Average.VclkFrequency;
 405        gpu_metrics->average_dclk_frequency = metrics.Average.DclkFrequency;
 406
 407        gpu_metrics->current_gfxclk = metrics.Current.GfxclkFrequency;
 408        gpu_metrics->current_socclk = metrics.Current.SocclkFrequency;
 409        gpu_metrics->current_uclk = metrics.Current.MemclkFrequency;
 410        gpu_metrics->current_fclk = metrics.Current.MemclkFrequency;
 411        gpu_metrics->current_vclk = metrics.Current.VclkFrequency;
 412        gpu_metrics->current_dclk = metrics.Current.DclkFrequency;
 413
 414        for (i = 0; i < 6; i++) {
 415                gpu_metrics->temperature_core[i] = metrics.Current.CoreTemperature[i];
 416                gpu_metrics->average_core_power[i] = metrics.Average.CorePower[i];
 417                gpu_metrics->current_coreclk[i] = metrics.Current.CoreFrequency[i];
 418        }
 419
 420        for (i = 0; i < 2; i++) {
 421                gpu_metrics->temperature_l3[i] = metrics.Current.L3Temperature[i];
 422                gpu_metrics->current_l3clk[i] = metrics.Current.L3Frequency[i];
 423        }
 424
 425        gpu_metrics->throttle_status = metrics.Current.ThrottlerStatus;
 426        gpu_metrics->system_clock_counter = ktime_get_boottime_ns();
 427
 428        *table = (void *)gpu_metrics;
 429
 430        return sizeof(struct gpu_metrics_v2_2);
 431}
 432
 433static int cyan_skillfish_od_edit_dpm_table(struct smu_context *smu,
 434                                        enum PP_OD_DPM_TABLE_COMMAND type,
 435                                        long input[], uint32_t size)
 436{
 437        int ret = 0;
 438        uint32_t vid;
 439
 440        switch (type) {
 441        case PP_OD_EDIT_VDDC_CURVE:
 442                if (size != 3 || input[0] != 0) {
 443                        dev_err(smu->adev->dev, "Invalid parameter!\n");
 444                        return -EINVAL;
 445                }
 446
 447                if (input[1] <= CYAN_SKILLFISH_SCLK_MIN ||
 448                        input[1] > CYAN_SKILLFISH_SCLK_MAX) {
 449                        dev_err(smu->adev->dev, "Invalid sclk! Valid sclk range: %uMHz - %uMhz\n",
 450                                        CYAN_SKILLFISH_SCLK_MIN, CYAN_SKILLFISH_SCLK_MAX);
 451                        return -EINVAL;
 452                }
 453
 454                if (input[2] <= CYAN_SKILLFISH_VDDC_MIN ||
 455                        input[2] > CYAN_SKILLFISH_VDDC_MAX) {
 456                        dev_err(smu->adev->dev, "Invalid vddc! Valid vddc range: %umV - %umV\n",
 457                                        CYAN_SKILLFISH_VDDC_MIN, CYAN_SKILLFISH_VDDC_MAX);
 458                        return -EINVAL;
 459                }
 460
 461                cyan_skillfish_user_settings.sclk = input[1];
 462                cyan_skillfish_user_settings.vddc = input[2];
 463
 464                break;
 465        case PP_OD_RESTORE_DEFAULT_TABLE:
 466                if (size != 0) {
 467                        dev_err(smu->adev->dev, "Invalid parameter!\n");
 468                        return -EINVAL;
 469                }
 470
 471                cyan_skillfish_user_settings.sclk = CYAN_SKILLFISH_SCLK_DEFAULT;
 472                cyan_skillfish_user_settings.vddc = CYAN_SKILLFISH_VDDC_MAGIC;
 473
 474                break;
 475        case PP_OD_COMMIT_DPM_TABLE:
 476                if (size != 0) {
 477                        dev_err(smu->adev->dev, "Invalid parameter!\n");
 478                        return -EINVAL;
 479                }
 480
 481                if (cyan_skillfish_user_settings.sclk < CYAN_SKILLFISH_SCLK_MIN ||
 482                    cyan_skillfish_user_settings.sclk > CYAN_SKILLFISH_SCLK_MAX) {
 483                        dev_err(smu->adev->dev, "Invalid sclk! Valid sclk range: %uMHz - %uMhz\n",
 484                                        CYAN_SKILLFISH_SCLK_MIN, CYAN_SKILLFISH_SCLK_MAX);
 485                        return -EINVAL;
 486                }
 487
 488                if ((cyan_skillfish_user_settings.vddc != CYAN_SKILLFISH_VDDC_MAGIC) &&
 489                        (cyan_skillfish_user_settings.vddc < CYAN_SKILLFISH_VDDC_MIN ||
 490                        cyan_skillfish_user_settings.vddc > CYAN_SKILLFISH_VDDC_MAX)) {
 491                        dev_err(smu->adev->dev, "Invalid vddc! Valid vddc range: %umV - %umV\n",
 492                                        CYAN_SKILLFISH_VDDC_MIN, CYAN_SKILLFISH_VDDC_MAX);
 493                        return -EINVAL;
 494                }
 495
 496                ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_RequestGfxclk,
 497                                        cyan_skillfish_user_settings.sclk, NULL);
 498                if (ret) {
 499                        dev_err(smu->adev->dev, "Set sclk failed!\n");
 500                        return ret;
 501                }
 502
 503                if (cyan_skillfish_user_settings.vddc == CYAN_SKILLFISH_VDDC_MAGIC) {
 504                        ret = smu_cmn_send_smc_msg(smu, SMU_MSG_UnforceGfxVid, NULL);
 505                        if (ret) {
 506                                dev_err(smu->adev->dev, "Unforce vddc failed!\n");
 507                                return ret;
 508                        }
 509                } else {
 510                        /*
 511                         * PMFW accepts SVI2 VID code, convert voltage to VID:
 512                         * vid = (uint32_t)((1.55 - voltage) * 160.0 + 0.00001)
 513                         */
 514                        vid = (1550 - cyan_skillfish_user_settings.vddc) * 160 / 1000;
 515                        ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_ForceGfxVid, vid, NULL);
 516                        if (ret) {
 517                                dev_err(smu->adev->dev, "Force vddc failed!\n");
 518                                return ret;
 519                        }
 520                }
 521
 522                break;
 523        default:
 524                return -EOPNOTSUPP;
 525        }
 526
 527        return ret;
 528}
 529
 530static const struct pptable_funcs cyan_skillfish_ppt_funcs = {
 531
 532        .check_fw_status = smu_v11_0_check_fw_status,
 533        .check_fw_version = smu_v11_0_check_fw_version,
 534        .init_power = smu_v11_0_init_power,
 535        .fini_power = smu_v11_0_fini_power,
 536        .init_smc_tables = cyan_skillfish_init_smc_tables,
 537        .fini_smc_tables = cyan_skillfish_finit_smc_tables,
 538        .read_sensor = cyan_skillfish_read_sensor,
 539        .print_clk_levels = cyan_skillfish_print_clk_levels,
 540        .is_dpm_running = cyan_skillfish_is_dpm_running,
 541        .get_gpu_metrics = cyan_skillfish_get_gpu_metrics,
 542        .od_edit_dpm_table = cyan_skillfish_od_edit_dpm_table,
 543        .register_irq_handler = smu_v11_0_register_irq_handler,
 544        .notify_memory_pool_location = smu_v11_0_notify_memory_pool_location,
 545        .send_smc_msg_with_param = smu_cmn_send_smc_msg_with_param,
 546        .send_smc_msg = smu_cmn_send_smc_msg,
 547        .set_driver_table_location = smu_v11_0_set_driver_table_location,
 548        .interrupt_work = smu_v11_0_interrupt_work,
 549};
 550
 551void cyan_skillfish_set_ppt_funcs(struct smu_context *smu)
 552{
 553        smu->ppt_funcs = &cyan_skillfish_ppt_funcs;
 554        smu->message_map = cyan_skillfish_message_map;
 555        smu->table_map = cyan_skillfish_table_map;
 556        smu->is_apu = true;
 557}
 558