drm/amd/pm: correct Arcturus mmTHM_BACO_CNTL register address
[linux-2.6-microblaze.git] / drivers / gpu / drm / amd / pm / swsmu / smu11 / smu_v11_0.c
index 624065d..a621185 100644 (file)
@@ -78,6 +78,9 @@ MODULE_FIRMWARE("amdgpu/dimgrey_cavefish_smc.bin");
 #define PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK 0xC000
 #define PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT 0xE
 
+#define mmTHM_BACO_CNTL_ARCT                   0xA7
+#define mmTHM_BACO_CNTL_ARCT_BASE_IDX          0
+
 static int link_width[] = {0, 1, 2, 4, 8, 12, 16};
 static int link_speed[] = {25, 50, 80, 160};
 
@@ -91,6 +94,11 @@ int smu_v11_0_init_microcode(struct smu_context *smu)
        const struct common_firmware_header *header;
        struct amdgpu_firmware_info *ucode = NULL;
 
+       if (amdgpu_sriov_vf(adev) &&
+                       ((adev->asic_type == CHIP_NAVI12) ||
+                        (adev->asic_type == CHIP_SIENNA_CICHLID)))
+               return 0;
+
        switch (adev->asic_type) {
        case CHIP_ARCTURUS:
                chip_name = "arcturus";
@@ -469,12 +477,14 @@ int smu_v11_0_fini_smc_tables(struct smu_context *smu)
 int smu_v11_0_init_power(struct smu_context *smu)
 {
        struct smu_power_context *smu_power = &smu->smu_power;
+       size_t size = smu->adev->asic_type == CHIP_VANGOGH ?
+                       sizeof(struct smu_11_5_power_context) :
+                       sizeof(struct smu_11_0_power_context);
 
-       smu_power->power_context = kzalloc(sizeof(struct smu_11_0_power_context),
-                                          GFP_KERNEL);
+       smu_power->power_context = kzalloc(size, GFP_KERNEL);
        if (!smu_power->power_context)
                return -ENOMEM;
-       smu_power->power_context_size = sizeof(struct smu_11_0_power_context);
+       smu_power->power_context_size = size;
 
        return 0;
 }
@@ -554,6 +564,7 @@ int smu_v11_0_get_vbios_bootup_values(struct smu_context *smu)
                smu->smu_table.boot_values.vdd_gfx = v_3_1->bootup_vddgfx_mv;
                smu->smu_table.boot_values.cooling_id = v_3_1->coolingsolution_id;
                smu->smu_table.boot_values.pp_table_id = 0;
+               smu->smu_table.boot_values.firmware_caps = v_3_1->firmware_capability;
                break;
        case 3:
        default:
@@ -569,6 +580,7 @@ int smu_v11_0_get_vbios_bootup_values(struct smu_context *smu)
                smu->smu_table.boot_values.vdd_gfx = v_3_3->bootup_vddgfx_mv;
                smu->smu_table.boot_values.cooling_id = v_3_3->coolingsolution_id;
                smu->smu_table.boot_values.pp_table_id = v_3_3->pplib_pptable_id;
+               smu->smu_table.boot_values.firmware_caps = v_3_3->firmware_capability;
        }
 
        smu->smu_table.boot_values.format_revision = header->format_revision;
@@ -929,9 +941,13 @@ int smu_v11_0_get_current_power_limit(struct smu_context *smu,
        if (power_src < 0)
                return -EINVAL;
 
+       /*
+        * BIT 24-31: ControllerId (only PPT0 is supported for now)
+        * BIT 16-23: PowerSource
+        */
        ret = smu_cmn_send_smc_msg_with_param(smu,
                                          SMU_MSG_GetPptLimit,
-                                         power_src << 16,
+                                         (0 << 24) | (power_src << 16),
                                          power_limit);
        if (ret)
                dev_err(smu->adev->dev, "[%s] get PPT limit failed!", __func__);
@@ -941,6 +957,7 @@ int smu_v11_0_get_current_power_limit(struct smu_context *smu,
 
 int smu_v11_0_set_power_limit(struct smu_context *smu, uint32_t n)
 {
+       int power_src;
        int ret = 0;
 
        if (!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT)) {
@@ -948,6 +965,22 @@ int smu_v11_0_set_power_limit(struct smu_context *smu, uint32_t n)
                return -EOPNOTSUPP;
        }
 
+       power_src = smu_cmn_to_asic_specific_index(smu,
+                                       CMN2ASIC_MAPPING_PWR,
+                                       smu->adev->pm.ac_power ?
+                                       SMU_POWER_SOURCE_AC :
+                                       SMU_POWER_SOURCE_DC);
+       if (power_src < 0)
+               return -EINVAL;
+
+       /*
+        * BIT 24-31: ControllerId (only PPT0 is supported for now)
+        * BIT 16-23: PowerSource
+        * BIT 0-15: PowerLimit
+        */
+       n &= 0xFFFF;
+       n |= 0 << 24;
+       n |= (power_src) << 16;
        ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetPptLimit, n, NULL);
        if (ret) {
                dev_err(smu->adev->dev, "[%s] Set power limit Failed!\n", __func__);
@@ -1091,6 +1124,7 @@ int smu_v11_0_gfx_off_control(struct smu_context *smu, bool enable)
        case CHIP_SIENNA_CICHLID:
        case CHIP_NAVY_FLOUNDER:
        case CHIP_DIMGREY_CAVEFISH:
+       case CHIP_VANGOGH:
                if (!(adev->pm.pp_feature & PP_GFXOFF_MASK))
                        return 0;
                if (enable)
@@ -1108,10 +1142,10 @@ int smu_v11_0_gfx_off_control(struct smu_context *smu, bool enable)
 uint32_t
 smu_v11_0_get_fan_control_mode(struct smu_context *smu)
 {
-       if (!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_FAN_CONTROL_BIT))
-               return AMD_FAN_CTRL_MANUAL;
-       else
+       if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_FAN_CONTROL_BIT))
                return AMD_FAN_CTRL_AUTO;
+       else
+               return smu->user_dpm_profile.fan_mode;
 }
 
 static int
@@ -1145,6 +1179,35 @@ smu_v11_0_set_fan_static_mode(struct smu_context *smu, uint32_t mode)
        return 0;
 }
 
+int
+smu_v11_0_set_fan_speed_percent(struct smu_context *smu, uint32_t speed)
+{
+       struct amdgpu_device *adev = smu->adev;
+       uint32_t duty100, duty;
+       uint64_t tmp64;
+
+       if (speed > 100)
+               speed = 100;
+
+       if (smu_v11_0_auto_fan_control(smu, 0))
+               return -EINVAL;
+
+       duty100 = REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL1),
+                               CG_FDO_CTRL1, FMAX_DUTY100);
+       if (!duty100)
+               return -EINVAL;
+
+       tmp64 = (uint64_t)speed * duty100;
+       do_div(tmp64, 100);
+       duty = (uint32_t)tmp64;
+
+       WREG32_SOC15(THM, 0, mmCG_FDO_CTRL0,
+                    REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL0),
+                                  CG_FDO_CTRL0, FDO_STATIC_DUTY, duty));
+
+       return smu_v11_0_set_fan_static_mode(smu, FDO_PWM_MODE_STATIC);
+}
+
 int
 smu_v11_0_set_fan_control_mode(struct smu_context *smu,
                               uint32_t mode)
@@ -1153,7 +1216,7 @@ smu_v11_0_set_fan_control_mode(struct smu_context *smu,
 
        switch (mode) {
        case AMD_FAN_CTRL_NONE:
-               ret = smu_v11_0_set_fan_speed_rpm(smu, smu->fan_max_rpm);
+               ret = smu_v11_0_set_fan_speed_percent(smu, 100);
                break;
        case AMD_FAN_CTRL_MANUAL:
                ret = smu_v11_0_auto_fan_control(smu, 0);
@@ -1173,58 +1236,6 @@ smu_v11_0_set_fan_control_mode(struct smu_context *smu,
        return ret;
 }
 
-int smu_v11_0_set_fan_speed_rpm(struct smu_context *smu,
-                                      uint32_t speed)
-{
-       struct amdgpu_device *adev = smu->adev;
-       int ret;
-       uint32_t tach_period, crystal_clock_freq;
-
-       if (!speed)
-               return -EINVAL;
-
-       ret = smu_v11_0_auto_fan_control(smu, 0);
-       if (ret)
-               return ret;
-
-       /*
-        * crystal_clock_freq div by 4 is required since the fan control
-        * module refers to 25MHz
-        */
-
-       crystal_clock_freq = amdgpu_asic_get_xclk(adev) / 4;
-       tach_period = 60 * crystal_clock_freq * 10000 / (8 * speed);
-       WREG32_SOC15(THM, 0, mmCG_TACH_CTRL,
-                    REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_TACH_CTRL),
-                                  CG_TACH_CTRL, TARGET_PERIOD,
-                                  tach_period));
-
-       ret = smu_v11_0_set_fan_static_mode(smu, FDO_PWM_MODE_STATIC_RPM);
-
-       return ret;
-}
-
-int smu_v11_0_get_fan_speed_rpm(struct smu_context *smu,
-                               uint32_t *speed)
-{
-       struct amdgpu_device *adev = smu->adev;
-       uint32_t tach_period, crystal_clock_freq;
-       uint64_t tmp64;
-
-       tach_period = REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_TACH_CTRL),
-                                   CG_TACH_CTRL, TARGET_PERIOD);
-       if (!tach_period)
-               return -EINVAL;
-
-       crystal_clock_freq = amdgpu_asic_get_xclk(adev);
-
-       tmp64 = (uint64_t)crystal_clock_freq * 60 * 10000;
-       do_div(tmp64, (tach_period * 8));
-       *speed = (uint32_t)tmp64;
-
-       return 0;
-}
-
 int smu_v11_0_set_xgmi_pstate(struct smu_context *smu,
                                     uint32_t pstate)
 {
@@ -1524,9 +1535,15 @@ int smu_v11_0_baco_set_state(struct smu_context *smu, enum smu_baco_state state)
                        break;
                default:
                        if (!ras || !ras->supported) {
-                               data = RREG32_SOC15(THM, 0, mmTHM_BACO_CNTL);
-                               data |= 0x80000000;
-                               WREG32_SOC15(THM, 0, mmTHM_BACO_CNTL, data);
+                               if (adev->asic_type == CHIP_ARCTURUS) {
+                                       data = RREG32_SOC15(THM, 0, mmTHM_BACO_CNTL_ARCT);
+                                       data |= 0x80000000;
+                                       WREG32_SOC15(THM, 0, mmTHM_BACO_CNTL_ARCT, data);
+                               } else {
+                                       data = RREG32_SOC15(THM, 0, mmTHM_BACO_CNTL);
+                                       data |= 0x80000000;
+                                       WREG32_SOC15(THM, 0, mmTHM_BACO_CNTL, data);
+                               }
 
                                ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_EnterBaco, 0, NULL);
                        } else {
@@ -2015,30 +2032,6 @@ int smu_v11_0_get_current_pcie_link_speed(struct smu_context *smu)
        return link_speed[speed_level];
 }
 
-void smu_v11_0_init_gpu_metrics_v1_0(struct gpu_metrics_v1_0 *gpu_metrics)
-{
-       memset(gpu_metrics, 0xFF, sizeof(struct gpu_metrics_v1_0));
-
-       gpu_metrics->common_header.structure_size =
-                               sizeof(struct gpu_metrics_v1_0);
-       gpu_metrics->common_header.format_revision = 1;
-       gpu_metrics->common_header.content_revision = 0;
-
-       gpu_metrics->system_clock_counter = ktime_get_boottime_ns();
-}
-
-void smu_v11_0_init_gpu_metrics_v2_0(struct gpu_metrics_v2_0 *gpu_metrics)
-{
-       memset(gpu_metrics, 0xFF, sizeof(struct gpu_metrics_v2_0));
-
-       gpu_metrics->common_header.structure_size =
-                               sizeof(struct gpu_metrics_v2_0);
-       gpu_metrics->common_header.format_revision = 2;
-       gpu_metrics->common_header.content_revision = 0;
-
-       gpu_metrics->system_clock_counter = ktime_get_boottime_ns();
-}
-
 int smu_v11_0_gfx_ulv_control(struct smu_context *smu,
                              bool enablement)
 {
@@ -2064,6 +2057,22 @@ int smu_v11_0_deep_sleep_control(struct smu_context *smu,
                }
        }
 
+       if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_DS_UCLK_BIT)) {
+               ret = smu_cmn_feature_set_enabled(smu, SMU_FEATURE_DS_UCLK_BIT, enablement);
+               if (ret) {
+                       dev_err(adev->dev, "Failed to %s UCLK DS!\n", enablement ? "enable" : "disable");
+                       return ret;
+               }
+       }
+
+       if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_DS_FCLK_BIT)) {
+               ret = smu_cmn_feature_set_enabled(smu, SMU_FEATURE_DS_FCLK_BIT, enablement);
+               if (ret) {
+                       dev_err(adev->dev, "Failed to %s FCLK DS!\n", enablement ? "enable" : "disable");
+                       return ret;
+               }
+       }
+
        if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_DS_SOCCLK_BIT)) {
                ret = smu_cmn_feature_set_enabled(smu, SMU_FEATURE_DS_SOCCLK_BIT, enablement);
                if (ret) {