linux/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.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 "vega10_thermal.h"
  25#include "vega10_hwmgr.h"
  26#include "vega10_ppsmc.h"
  27#include "vega10_inc.h"
  28#include "pp_soc15.h"
  29#include "pp_debug.h"
  30
  31static int vega10_get_current_rpm(struct pp_hwmgr *hwmgr, uint32_t *current_rpm)
  32{
  33        smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentRpm);
  34        *current_rpm = smum_get_argument(hwmgr);
  35        return 0;
  36}
  37
  38int vega10_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr,
  39                struct phm_fan_speed_info *fan_speed_info)
  40{
  41
  42        if (hwmgr->thermal_controller.fanInfo.bNoFan)
  43                return 0;
  44
  45        fan_speed_info->supports_percent_read = true;
  46        fan_speed_info->supports_percent_write = true;
  47        fan_speed_info->min_percent = 0;
  48        fan_speed_info->max_percent = 100;
  49
  50        if (PP_CAP(PHM_PlatformCaps_FanSpeedInTableIsRPM) &&
  51                hwmgr->thermal_controller.fanInfo.
  52                ucTachometerPulsesPerRevolution) {
  53                fan_speed_info->supports_rpm_read = true;
  54                fan_speed_info->supports_rpm_write = true;
  55                fan_speed_info->min_rpm =
  56                                hwmgr->thermal_controller.fanInfo.ulMinRPM;
  57                fan_speed_info->max_rpm =
  58                                hwmgr->thermal_controller.fanInfo.ulMaxRPM;
  59        } else {
  60                fan_speed_info->min_rpm = 0;
  61                fan_speed_info->max_rpm = 0;
  62        }
  63
  64        return 0;
  65}
  66
  67int vega10_fan_ctrl_get_fan_speed_percent(struct pp_hwmgr *hwmgr,
  68                uint32_t *speed)
  69{
  70        uint32_t current_rpm;
  71        uint32_t percent = 0;
  72
  73        if (hwmgr->thermal_controller.fanInfo.bNoFan)
  74                return 0;
  75
  76        if (vega10_get_current_rpm(hwmgr, &current_rpm))
  77                return -1;
  78
  79        if (hwmgr->thermal_controller.
  80                        advanceFanControlParameters.usMaxFanRPM != 0)
  81                percent = current_rpm * 100 /
  82                        hwmgr->thermal_controller.
  83                        advanceFanControlParameters.usMaxFanRPM;
  84
  85        *speed = percent > 100 ? 100 : percent;
  86
  87        return 0;
  88}
  89
  90int vega10_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t *speed)
  91{
  92        struct vega10_hwmgr *data = hwmgr->backend;
  93        uint32_t tach_period;
  94        uint32_t crystal_clock_freq;
  95        int result = 0;
  96
  97        if (hwmgr->thermal_controller.fanInfo.bNoFan)
  98                return -1;
  99
 100        if (data->smu_features[GNLD_FAN_CONTROL].supported) {
 101                result = vega10_get_current_rpm(hwmgr, speed);
 102        } else {
 103                uint32_t reg = soc15_get_register_offset(THM_HWID, 0,
 104                                mmCG_TACH_STATUS_BASE_IDX, mmCG_TACH_STATUS);
 105                tach_period =
 106                        CGS_REG_GET_FIELD(cgs_read_register(hwmgr->device, reg),
 107                                          CG_TACH_STATUS,
 108                                          TACH_PERIOD);
 109
 110                if (tach_period == 0)
 111                        return -EINVAL;
 112
 113                crystal_clock_freq = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev);
 114
 115                *speed = 60 * crystal_clock_freq * 10000 / tach_period;
 116        }
 117
 118        return result;
 119}
 120
 121/**
 122* Set Fan Speed Control to static mode,
 123* so that the user can decide what speed to use.
 124* @param    hwmgr  the address of the powerplay hardware manager.
 125*           mode the fan control mode, 0 default, 1 by percent, 5, by RPM
 126* @exception Should always succeed.
 127*/
 128int vega10_fan_ctrl_set_static_mode(struct pp_hwmgr *hwmgr, uint32_t mode)
 129{
 130        uint32_t reg;
 131
 132        reg = soc15_get_register_offset(THM_HWID, 0,
 133                        mmCG_FDO_CTRL2_BASE_IDX, mmCG_FDO_CTRL2);
 134
 135        if (hwmgr->fan_ctrl_is_in_default_mode) {
 136                hwmgr->fan_ctrl_default_mode =
 137                        CGS_REG_GET_FIELD(cgs_read_register(hwmgr->device, reg),
 138                                CG_FDO_CTRL2, FDO_PWM_MODE);
 139                hwmgr->tmin =
 140                        CGS_REG_GET_FIELD(cgs_read_register(hwmgr->device, reg),
 141                                CG_FDO_CTRL2, TMIN);
 142                hwmgr->fan_ctrl_is_in_default_mode = false;
 143        }
 144
 145        cgs_write_register(hwmgr->device, reg,
 146                        CGS_REG_SET_FIELD(cgs_read_register(hwmgr->device, reg),
 147                                CG_FDO_CTRL2, TMIN, 0));
 148        cgs_write_register(hwmgr->device, reg,
 149                        CGS_REG_SET_FIELD(cgs_read_register(hwmgr->device, reg),
 150                                CG_FDO_CTRL2, FDO_PWM_MODE, mode));
 151
 152        return 0;
 153}
 154
 155/**
 156* Reset Fan Speed Control to default mode.
 157* @param    hwmgr  the address of the powerplay hardware manager.
 158* @exception Should always succeed.
 159*/
 160int vega10_fan_ctrl_set_default_mode(struct pp_hwmgr *hwmgr)
 161{
 162        uint32_t reg;
 163
 164        reg = soc15_get_register_offset(THM_HWID, 0,
 165                        mmCG_FDO_CTRL2_BASE_IDX, mmCG_FDO_CTRL2);
 166
 167        if (!hwmgr->fan_ctrl_is_in_default_mode) {
 168                cgs_write_register(hwmgr->device, reg,
 169                        CGS_REG_SET_FIELD(cgs_read_register(hwmgr->device, reg),
 170                                CG_FDO_CTRL2, FDO_PWM_MODE,
 171                                hwmgr->fan_ctrl_default_mode));
 172                cgs_write_register(hwmgr->device, reg,
 173                        CGS_REG_SET_FIELD(cgs_read_register(hwmgr->device, reg),
 174                                CG_FDO_CTRL2, TMIN,
 175                                hwmgr->tmin << CG_FDO_CTRL2__TMIN__SHIFT));
 176                hwmgr->fan_ctrl_is_in_default_mode = true;
 177        }
 178
 179        return 0;
 180}
 181
 182/**
 183 * @fn vega10_enable_fan_control_feature
 184 * @brief Enables the SMC Fan Control Feature.
 185 *
 186 * @param    hwmgr - the address of the powerplay hardware manager.
 187 * @return   0 on success. -1 otherwise.
 188 */
 189static int vega10_enable_fan_control_feature(struct pp_hwmgr *hwmgr)
 190{
 191        struct vega10_hwmgr *data = hwmgr->backend;
 192
 193        if (data->smu_features[GNLD_FAN_CONTROL].supported) {
 194                PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(
 195                                hwmgr, true,
 196                                data->smu_features[GNLD_FAN_CONTROL].
 197                                smu_feature_bitmap),
 198                                "Attempt to Enable FAN CONTROL feature Failed!",
 199                                return -1);
 200                data->smu_features[GNLD_FAN_CONTROL].enabled = true;
 201        }
 202
 203        return 0;
 204}
 205
 206static int vega10_disable_fan_control_feature(struct pp_hwmgr *hwmgr)
 207{
 208        struct vega10_hwmgr *data = hwmgr->backend;
 209
 210        if (data->smu_features[GNLD_FAN_CONTROL].supported) {
 211                PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(
 212                                hwmgr, false,
 213                                data->smu_features[GNLD_FAN_CONTROL].
 214                                smu_feature_bitmap),
 215                                "Attempt to Enable FAN CONTROL feature Failed!",
 216                                return -1);
 217                data->smu_features[GNLD_FAN_CONTROL].enabled = false;
 218        }
 219
 220        return 0;
 221}
 222
 223int vega10_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr)
 224{
 225        if (hwmgr->thermal_controller.fanInfo.bNoFan)
 226                return -1;
 227
 228        PP_ASSERT_WITH_CODE(!vega10_enable_fan_control_feature(hwmgr),
 229                        "Attempt to Enable SMC FAN CONTROL Feature Failed!",
 230                        return -1);
 231
 232        return 0;
 233}
 234
 235
 236int vega10_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr)
 237{
 238        struct vega10_hwmgr *data = hwmgr->backend;
 239
 240        if (hwmgr->thermal_controller.fanInfo.bNoFan)
 241                return -1;
 242
 243        if (data->smu_features[GNLD_FAN_CONTROL].supported) {
 244                PP_ASSERT_WITH_CODE(!vega10_disable_fan_control_feature(hwmgr),
 245                                "Attempt to Disable SMC FAN CONTROL Feature Failed!",
 246                                return -1);
 247        }
 248        return 0;
 249}
 250
 251/**
 252* Set Fan Speed in percent.
 253* @param    hwmgr  the address of the powerplay hardware manager.
 254* @param    speed is the percentage value (0% - 100%) to be set.
 255* @exception Fails is the 100% setting appears to be 0.
 256*/
 257int vega10_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr,
 258                uint32_t speed)
 259{
 260        uint32_t duty100;
 261        uint32_t duty;
 262        uint64_t tmp64;
 263        uint32_t reg;
 264
 265        if (hwmgr->thermal_controller.fanInfo.bNoFan)
 266                return 0;
 267
 268        if (speed > 100)
 269                speed = 100;
 270
 271        if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl))
 272                vega10_fan_ctrl_stop_smc_fan_control(hwmgr);
 273
 274        reg = soc15_get_register_offset(THM_HWID, 0,
 275                        mmCG_FDO_CTRL1_BASE_IDX, mmCG_FDO_CTRL1);
 276
 277        duty100 = CGS_REG_GET_FIELD(cgs_read_register(hwmgr->device, reg),
 278                                    CG_FDO_CTRL1, FMAX_DUTY100);
 279
 280        if (duty100 == 0)
 281                return -EINVAL;
 282
 283        tmp64 = (uint64_t)speed * duty100;
 284        do_div(tmp64, 100);
 285        duty = (uint32_t)tmp64;
 286
 287        reg = soc15_get_register_offset(THM_HWID, 0,
 288                        mmCG_FDO_CTRL0_BASE_IDX, mmCG_FDO_CTRL0);
 289        cgs_write_register(hwmgr->device, reg,
 290                CGS_REG_SET_FIELD(cgs_read_register(hwmgr->device, reg),
 291                        CG_FDO_CTRL0, FDO_STATIC_DUTY, duty));
 292
 293        return vega10_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC);
 294}
 295
 296/**
 297* Reset Fan Speed to default.
 298* @param    hwmgr  the address of the powerplay hardware manager.
 299* @exception Always succeeds.
 300*/
 301int vega10_fan_ctrl_reset_fan_speed_to_default(struct pp_hwmgr *hwmgr)
 302{
 303        if (hwmgr->thermal_controller.fanInfo.bNoFan)
 304                return 0;
 305
 306        if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl))
 307                return vega10_fan_ctrl_start_smc_fan_control(hwmgr);
 308        else
 309                return vega10_fan_ctrl_set_default_mode(hwmgr);
 310}
 311
 312/**
 313* Set Fan Speed in RPM.
 314* @param    hwmgr  the address of the powerplay hardware manager.
 315* @param    speed is the percentage value (min - max) to be set.
 316* @exception Fails is the speed not lie between min and max.
 317*/
 318int vega10_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed)
 319{
 320        uint32_t tach_period;
 321        uint32_t crystal_clock_freq;
 322        int result = 0;
 323        uint32_t reg;
 324
 325        if (hwmgr->thermal_controller.fanInfo.bNoFan ||
 326            (speed < hwmgr->thermal_controller.fanInfo.ulMinRPM) ||
 327            (speed > hwmgr->thermal_controller.fanInfo.ulMaxRPM))
 328                return -1;
 329
 330        if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl))
 331                result = vega10_fan_ctrl_stop_smc_fan_control(hwmgr);
 332
 333        if (!result) {
 334                crystal_clock_freq = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev);
 335                tach_period = 60 * crystal_clock_freq * 10000 / (8 * speed);
 336                reg = soc15_get_register_offset(THM_HWID, 0,
 337                                mmCG_TACH_STATUS_BASE_IDX, mmCG_TACH_STATUS);
 338                cgs_write_register(hwmgr->device, reg,
 339                                CGS_REG_SET_FIELD(cgs_read_register(hwmgr->device, reg),
 340                                        CG_TACH_STATUS, TACH_PERIOD,
 341                                        tach_period));
 342        }
 343        return vega10_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC_RPM);
 344}
 345
 346/**
 347* Reads the remote temperature from the SIslands thermal controller.
 348*
 349* @param    hwmgr The address of the hardware manager.
 350*/
 351int vega10_thermal_get_temperature(struct pp_hwmgr *hwmgr)
 352{
 353        int temp;
 354        uint32_t reg;
 355
 356        reg = soc15_get_register_offset(THM_HWID, 0,
 357                        mmCG_MULT_THERMAL_STATUS_BASE_IDX,  mmCG_MULT_THERMAL_STATUS);
 358
 359        temp = cgs_read_register(hwmgr->device, reg);
 360
 361        temp = (temp & CG_MULT_THERMAL_STATUS__CTF_TEMP_MASK) >>
 362                        CG_MULT_THERMAL_STATUS__CTF_TEMP__SHIFT;
 363
 364        temp = temp & 0x1ff;
 365
 366        temp *= PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
 367
 368        return temp;
 369}
 370
 371/**
 372* Set the requested temperature range for high and low alert signals
 373*
 374* @param    hwmgr The address of the hardware manager.
 375* @param    range Temperature range to be programmed for
 376*           high and low alert signals
 377* @exception PP_Result_BadInput if the input data is not valid.
 378*/
 379static int vega10_thermal_set_temperature_range(struct pp_hwmgr *hwmgr,
 380                struct PP_TemperatureRange *range)
 381{
 382        int low = VEGA10_THERMAL_MINIMUM_ALERT_TEMP *
 383                        PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
 384        int high = VEGA10_THERMAL_MAXIMUM_ALERT_TEMP *
 385                        PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
 386        uint32_t val, reg;
 387
 388        if (low < range->min)
 389                low = range->min;
 390        if (high > range->max)
 391                high = range->max;
 392
 393        if (low > high)
 394                return -EINVAL;
 395
 396        reg = soc15_get_register_offset(THM_HWID, 0,
 397                        mmTHM_THERMAL_INT_CTRL_BASE_IDX, mmTHM_THERMAL_INT_CTRL);
 398
 399        val = cgs_read_register(hwmgr->device, reg);
 400
 401        val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, MAX_IH_CREDIT, 5);
 402        val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_IH_HW_ENA, 1);
 403        val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, (high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES));
 404        val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, (low / PP_TEMPERATURE_UNITS_PER_CENTIGRADES));
 405        val &= (~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK) &
 406                        (~THM_THERMAL_INT_CTRL__THERM_INTH_MASK_MASK) &
 407                        (~THM_THERMAL_INT_CTRL__THERM_INTL_MASK_MASK);
 408
 409        cgs_write_register(hwmgr->device, reg, val);
 410
 411        return 0;
 412}
 413
 414/**
 415* Programs thermal controller one-time setting registers
 416*
 417* @param    hwmgr The address of the hardware manager.
 418*/
 419static int vega10_thermal_initialize(struct pp_hwmgr *hwmgr)
 420{
 421        uint32_t reg;
 422
 423        if (hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution) {
 424                reg = soc15_get_register_offset(THM_HWID, 0,
 425                                mmCG_TACH_CTRL_BASE_IDX, mmCG_TACH_CTRL);
 426                cgs_write_register(hwmgr->device, reg,
 427                        CGS_REG_SET_FIELD(cgs_read_register(hwmgr->device, reg),
 428                                CG_TACH_CTRL, EDGE_PER_REV,
 429                                hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution - 1));
 430        }
 431
 432        reg = soc15_get_register_offset(THM_HWID, 0,
 433                        mmCG_FDO_CTRL2_BASE_IDX, mmCG_FDO_CTRL2);
 434        cgs_write_register(hwmgr->device, reg,
 435                CGS_REG_SET_FIELD(cgs_read_register(hwmgr->device, reg),
 436                        CG_FDO_CTRL2, TACH_PWM_RESP_RATE, 0x28));
 437
 438        return 0;
 439}
 440
 441/**
 442* Enable thermal alerts on the RV770 thermal controller.
 443*
 444* @param    hwmgr The address of the hardware manager.
 445*/
 446static int vega10_thermal_enable_alert(struct pp_hwmgr *hwmgr)
 447{
 448        struct vega10_hwmgr *data = hwmgr->backend;
 449        uint32_t val = 0;
 450        uint32_t reg;
 451
 452        if (data->smu_features[GNLD_FW_CTF].supported) {
 453                if (data->smu_features[GNLD_FW_CTF].enabled)
 454                        printk("[Thermal_EnableAlert] FW CTF Already Enabled!\n");
 455
 456                PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr,
 457                                true,
 458                                data->smu_features[GNLD_FW_CTF].smu_feature_bitmap),
 459                                "Attempt to Enable FW CTF feature Failed!",
 460                                return -1);
 461                data->smu_features[GNLD_FW_CTF].enabled = true;
 462        }
 463
 464        val |= (1 << THM_THERMAL_INT_ENA__THERM_INTH_CLR__SHIFT);
 465        val |= (1 << THM_THERMAL_INT_ENA__THERM_INTL_CLR__SHIFT);
 466        val |= (1 << THM_THERMAL_INT_ENA__THERM_TRIGGER_CLR__SHIFT);
 467
 468        reg = soc15_get_register_offset(THM_HWID, 0, mmTHM_THERMAL_INT_ENA_BASE_IDX, mmTHM_THERMAL_INT_ENA);
 469        cgs_write_register(hwmgr->device, reg, val);
 470
 471        return 0;
 472}
 473
 474/**
 475* Disable thermal alerts on the RV770 thermal controller.
 476* @param    hwmgr The address of the hardware manager.
 477*/
 478int vega10_thermal_disable_alert(struct pp_hwmgr *hwmgr)
 479{
 480        struct vega10_hwmgr *data = hwmgr->backend;
 481        uint32_t reg;
 482
 483        if (data->smu_features[GNLD_FW_CTF].supported) {
 484                if (!data->smu_features[GNLD_FW_CTF].enabled)
 485                        printk("[Thermal_EnableAlert] FW CTF Already disabled!\n");
 486
 487
 488                PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr,
 489                        false,
 490                        data->smu_features[GNLD_FW_CTF].smu_feature_bitmap),
 491                        "Attempt to disable FW CTF feature Failed!",
 492                        return -1);
 493                data->smu_features[GNLD_FW_CTF].enabled = false;
 494        }
 495
 496        reg = soc15_get_register_offset(THM_HWID, 0, mmTHM_THERMAL_INT_ENA_BASE_IDX, mmTHM_THERMAL_INT_ENA);
 497        cgs_write_register(hwmgr->device, reg, 0);
 498
 499        return 0;
 500}
 501
 502/**
 503* Uninitialize the thermal controller.
 504* Currently just disables alerts.
 505* @param    hwmgr The address of the hardware manager.
 506*/
 507int vega10_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr)
 508{
 509        int result = vega10_thermal_disable_alert(hwmgr);
 510
 511        if (!hwmgr->thermal_controller.fanInfo.bNoFan)
 512                vega10_fan_ctrl_set_default_mode(hwmgr);
 513
 514        return result;
 515}
 516
 517/**
 518* Set up the fan table to control the fan using the SMC.
 519* @param    hwmgr  the address of the powerplay hardware manager.
 520* @param    pInput the pointer to input data
 521* @param    pOutput the pointer to output data
 522* @param    pStorage the pointer to temporary storage
 523* @param    Result the last failure code
 524* @return   result from set temperature range routine
 525*/
 526int vega10_thermal_setup_fan_table(struct pp_hwmgr *hwmgr)
 527{
 528        int ret;
 529        struct vega10_hwmgr *data = hwmgr->backend;
 530        PPTable_t *table = &(data->smc_state_table.pp_table);
 531
 532        if (!data->smu_features[GNLD_FAN_CONTROL].supported)
 533                return 0;
 534
 535        table->FanMaximumRpm = (uint16_t)hwmgr->thermal_controller.
 536                        advanceFanControlParameters.usMaxFanRPM;
 537        table->FanThrottlingRpm = hwmgr->thermal_controller.
 538                        advanceFanControlParameters.usFanRPMMaxLimit;
 539        table->FanAcousticLimitRpm = (uint16_t)(hwmgr->thermal_controller.
 540                        advanceFanControlParameters.ulMinFanSCLKAcousticLimit);
 541        table->FanTargetTemperature = hwmgr->thermal_controller.
 542                        advanceFanControlParameters.usTMax;
 543
 544        smum_send_msg_to_smc_with_parameter(hwmgr,
 545                                PPSMC_MSG_SetFanTemperatureTarget,
 546                                (uint32_t)table->FanTargetTemperature);
 547
 548        table->FanPwmMin = hwmgr->thermal_controller.
 549                        advanceFanControlParameters.usPWMMin * 255 / 100;
 550        table->FanTargetGfxclk = (uint16_t)(hwmgr->thermal_controller.
 551                        advanceFanControlParameters.ulTargetGfxClk);
 552        table->FanGainEdge = hwmgr->thermal_controller.
 553                        advanceFanControlParameters.usFanGainEdge;
 554        table->FanGainHotspot = hwmgr->thermal_controller.
 555                        advanceFanControlParameters.usFanGainHotspot;
 556        table->FanGainLiquid = hwmgr->thermal_controller.
 557                        advanceFanControlParameters.usFanGainLiquid;
 558        table->FanGainVrVddc = hwmgr->thermal_controller.
 559                        advanceFanControlParameters.usFanGainVrVddc;
 560        table->FanGainVrMvdd = hwmgr->thermal_controller.
 561                        advanceFanControlParameters.usFanGainVrMvdd;
 562        table->FanGainPlx = hwmgr->thermal_controller.
 563                        advanceFanControlParameters.usFanGainPlx;
 564        table->FanGainHbm = hwmgr->thermal_controller.
 565                        advanceFanControlParameters.usFanGainHbm;
 566        table->FanZeroRpmEnable = hwmgr->thermal_controller.
 567                        advanceFanControlParameters.ucEnableZeroRPM;
 568        table->FanStopTemp = hwmgr->thermal_controller.
 569                        advanceFanControlParameters.usZeroRPMStopTemperature;
 570        table->FanStartTemp = hwmgr->thermal_controller.
 571                        advanceFanControlParameters.usZeroRPMStartTemperature;
 572
 573        ret = smum_smc_table_manager(hwmgr,
 574                                (uint8_t *)(&(data->smc_state_table.pp_table)),
 575                                PPTABLE, false);
 576        if (ret)
 577                pr_info("Failed to update Fan Control Table in PPTable!");
 578
 579        return ret;
 580}
 581
 582/**
 583* Start the fan control on the SMC.
 584* @param    hwmgr  the address of the powerplay hardware manager.
 585* @param    pInput the pointer to input data
 586* @param    pOutput the pointer to output data
 587* @param    pStorage the pointer to temporary storage
 588* @param    Result the last failure code
 589* @return   result from set temperature range routine
 590*/
 591int vega10_thermal_start_smc_fan_control(struct pp_hwmgr *hwmgr)
 592{
 593/* If the fantable setup has failed we could have disabled
 594 * PHM_PlatformCaps_MicrocodeFanControl even after
 595 * this function was included in the table.
 596 * Make sure that we still think controlling the fan is OK.
 597*/
 598        if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl))
 599                vega10_fan_ctrl_start_smc_fan_control(hwmgr);
 600
 601        return 0;
 602}
 603
 604
 605int vega10_start_thermal_controller(struct pp_hwmgr *hwmgr,
 606                                struct PP_TemperatureRange *range)
 607{
 608        int ret = 0;
 609
 610        if (range == NULL)
 611                return -EINVAL;
 612
 613        vega10_thermal_initialize(hwmgr);
 614        ret = vega10_thermal_set_temperature_range(hwmgr, range);
 615        if (ret)
 616                return -EINVAL;
 617
 618        vega10_thermal_enable_alert(hwmgr);
 619/* We should restrict performance levels to low before we halt the SMC.
 620 * On the other hand we are still in boot state when we do this
 621 * so it would be pointless.
 622 * If this assumption changes we have to revisit this table.
 623 */
 624        ret = vega10_thermal_setup_fan_table(hwmgr);
 625        if (ret)
 626                return -EINVAL;
 627
 628        vega10_thermal_start_smc_fan_control(hwmgr);
 629
 630        return 0;
 631};
 632
 633
 634
 635
 636int vega10_thermal_ctrl_uninitialize_thermal_controller(struct pp_hwmgr *hwmgr)
 637{
 638        if (!hwmgr->thermal_controller.fanInfo.bNoFan) {
 639                vega10_fan_ctrl_set_default_mode(hwmgr);
 640                vega10_fan_ctrl_stop_smc_fan_control(hwmgr);
 641        }
 642        return 0;
 643}
 644