summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/pm
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/pm')
-rw-r--r--drivers/gpu/drm/amd/pm/amdgpu_pm.c154
-rw-r--r--drivers/gpu/drm/amd/pm/inc/smu_v13_0_0_pptable.h203
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c136
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h18
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu11_driver_if_sienna_cichlid.h63
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_0.h1544
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_4.h267
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_7.h1562
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_0_ppsmc.h141
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_4_pmfw.h137
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_4_ppsmc.h138
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_7_ppsmc.h134
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h28
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h58
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0_7_pptable.h200
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c178
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c60
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/Makefile3
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.h8
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c697
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c1648
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.h28
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.c1044
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.h28
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c1597
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.h28
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c62
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c24
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h2
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu_internal.h1
30 files changed, 9874 insertions, 317 deletions
diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c
index 78ec9b71197d..5e318b3f6c0f 100644
--- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c
+++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c
@@ -66,7 +66,8 @@ static const struct cg_flag_name clocks[] = {
{AMD_CG_SUPPORT_HDP_SD, "Host Data Path Shutdown"},
{AMD_CG_SUPPORT_IH_CG, "Interrupt Handler Clock Gating"},
{AMD_CG_SUPPORT_JPEG_MGCG, "JPEG Medium Grain Clock Gating"},
-
+ {AMD_CG_SUPPORT_REPEATER_FGCG, "Repeater Fine Grain Clock Gating"},
+ {AMD_CG_SUPPORT_GFX_PERF_CLK, "Perfmon Clock Gating"},
{AMD_CG_SUPPORT_ATHUB_MGCG, "Address Translation Hub Medium Grain Clock Gating"},
{AMD_CG_SUPPORT_ATHUB_LS, "Address Translation Hub Light Sleep"},
{0, NULL},
@@ -88,7 +89,8 @@ const char * const amdgpu_pp_profile_name[] = {
"VIDEO",
"VR",
"COMPUTE",
- "CUSTOM"
+ "CUSTOM",
+ "WINDOW_3D",
};
/**
@@ -1732,22 +1734,11 @@ out:
return size;
}
-/**
- * DOC: smartshift_apu_power
- *
- * The amdgpu driver provides a sysfs API for reporting APU power
- * share if it supports smartshift. The value is expressed as
- * the proportion of stapm limit where stapm limit is the total APU
- * power limit. The result is in percentage. If APU power is 130% of
- * STAPM, then APU is using 30% of the dGPU's headroom.
- */
-
-static ssize_t amdgpu_get_smartshift_apu_power(struct device *dev, struct device_attribute *attr,
- char *buf)
+static int amdgpu_device_read_powershift(struct amdgpu_device *adev,
+ uint32_t *ss_power, bool dgpu_share)
{
- struct drm_device *ddev = dev_get_drvdata(dev);
- struct amdgpu_device *adev = drm_to_adev(ddev);
- uint32_t ss_power, size;
+ struct drm_device *ddev = adev_to_drm(adev);
+ uint32_t size;
int r = 0;
if (amdgpu_in_reset(adev))
@@ -1761,61 +1752,77 @@ static ssize_t amdgpu_get_smartshift_apu_power(struct device *dev, struct device
return r;
}
- r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_SS_APU_SHARE,
- (void *)&ss_power, &size);
- if (r)
- goto out;
-
- r = sysfs_emit(buf, "%u%%\n", ss_power);
+ if (dgpu_share)
+ r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_SS_DGPU_SHARE,
+ (void *)ss_power, &size);
+ else
+ r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_SS_APU_SHARE,
+ (void *)ss_power, &size);
-out:
pm_runtime_mark_last_busy(ddev->dev);
pm_runtime_put_autosuspend(ddev->dev);
return r;
}
-/**
- * DOC: smartshift_dgpu_power
- *
- * The amdgpu driver provides a sysfs API for reporting the dGPU power
- * share if the device is in HG and supports smartshift. The value
- * is expressed as the proportion of stapm limit where stapm limit
- * is the total APU power limit. The value is in percentage. If dGPU
- * power is 20% higher than STAPM power(120%), it's using 20% of the
- * APU's power headroom.
- */
-
-static ssize_t amdgpu_get_smartshift_dgpu_power(struct device *dev, struct device_attribute *attr,
- char *buf)
+static int amdgpu_show_powershift_percent(struct device *dev,
+ char *buf, bool dgpu_share)
{
struct drm_device *ddev = dev_get_drvdata(dev);
struct amdgpu_device *adev = drm_to_adev(ddev);
- uint32_t ss_power, size;
- int r = 0;
-
- if (amdgpu_in_reset(adev))
- return -EPERM;
- if (adev->in_suspend && !adev->in_runpm)
- return -EPERM;
-
- r = pm_runtime_get_sync(ddev->dev);
- if (r < 0) {
- pm_runtime_put_autosuspend(ddev->dev);
- return r;
+ uint32_t ss_power;
+ int r = 0, i;
+
+ r = amdgpu_device_read_powershift(adev, &ss_power, dgpu_share);
+ if (r == -EOPNOTSUPP) {
+ /* sensor not available on dGPU, try to read from APU */
+ adev = NULL;
+ mutex_lock(&mgpu_info.mutex);
+ for (i = 0; i < mgpu_info.num_gpu; i++) {
+ if (mgpu_info.gpu_ins[i].adev->flags & AMD_IS_APU) {
+ adev = mgpu_info.gpu_ins[i].adev;
+ break;
+ }
+ }
+ mutex_unlock(&mgpu_info.mutex);
+ if (adev)
+ r = amdgpu_device_read_powershift(adev, &ss_power, dgpu_share);
}
- r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_SS_DGPU_SHARE,
- (void *)&ss_power, &size);
+ if (!r)
+ r = sysfs_emit(buf, "%u%%\n", ss_power);
- if (r)
- goto out;
+ return r;
+}
+/**
+ * DOC: smartshift_apu_power
+ *
+ * The amdgpu driver provides a sysfs API for reporting APU power
+ * shift in percentage if platform supports smartshift. Value 0 means that
+ * there is no powershift and values between [1-100] means that the power
+ * is shifted to APU, the percentage of boost is with respect to APU power
+ * limit on the platform.
+ */
- r = sysfs_emit(buf, "%u%%\n", ss_power);
+static ssize_t amdgpu_get_smartshift_apu_power(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ return amdgpu_show_powershift_percent(dev, buf, false);
+}
-out:
- pm_runtime_mark_last_busy(ddev->dev);
- pm_runtime_put_autosuspend(ddev->dev);
- return r;
+/**
+ * DOC: smartshift_dgpu_power
+ *
+ * The amdgpu driver provides a sysfs API for reporting dGPU power
+ * shift in percentage if platform supports smartshift. Value 0 means that
+ * there is no powershift and values between [1-100] means that the power is
+ * shifted to dGPU, the percentage of boost is with respect to dGPU power
+ * limit on the platform.
+ */
+
+static ssize_t amdgpu_get_smartshift_dgpu_power(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ return amdgpu_show_powershift_percent(dev, buf, true);
}
/**
@@ -1882,18 +1889,7 @@ out:
static int ss_power_attr_update(struct amdgpu_device *adev, struct amdgpu_device_attr *attr,
uint32_t mask, enum amdgpu_device_attr_states *states)
{
- uint32_t ss_power, size;
-
- if (!amdgpu_acpi_is_power_shift_control_supported())
- *states = ATTR_STATE_UNSUPPORTED;
- else if ((adev->flags & AMD_IS_PX) &&
- !amdgpu_device_supports_smart_shift(adev_to_drm(adev)))
- *states = ATTR_STATE_UNSUPPORTED;
- else if (amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_SS_APU_SHARE,
- (void *)&ss_power, &size))
- *states = ATTR_STATE_UNSUPPORTED;
- else if (amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_SS_DGPU_SHARE,
- (void *)&ss_power, &size))
+ if (!amdgpu_device_supports_smart_shift(adev_to_drm(adev)))
*states = ATTR_STATE_UNSUPPORTED;
return 0;
@@ -1994,6 +1990,7 @@ static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_
case IP_VERSION(9, 4, 1):
case IP_VERSION(9, 4, 2):
case IP_VERSION(10, 3, 0):
+ case IP_VERSION(11, 0, 0):
*states = ATTR_STATE_SUPPORTED;
break;
default:
@@ -2008,16 +2005,22 @@ static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_
} else if (DEVICE_ATTR_IS(pp_dpm_vclk)) {
if (!(gc_ver == IP_VERSION(10, 3, 1) ||
gc_ver == IP_VERSION(10, 3, 0) ||
- gc_ver == IP_VERSION(10, 1, 2)))
+ gc_ver == IP_VERSION(10, 1, 2) ||
+ gc_ver == IP_VERSION(11, 0, 0) ||
+ gc_ver == IP_VERSION(11, 0, 2)))
*states = ATTR_STATE_UNSUPPORTED;
} else if (DEVICE_ATTR_IS(pp_dpm_dclk)) {
if (!(gc_ver == IP_VERSION(10, 3, 1) ||
gc_ver == IP_VERSION(10, 3, 0) ||
- gc_ver == IP_VERSION(10, 1, 2)))
+ gc_ver == IP_VERSION(10, 1, 2) ||
+ gc_ver == IP_VERSION(11, 0, 0) ||
+ gc_ver == IP_VERSION(11, 0, 2)))
*states = ATTR_STATE_UNSUPPORTED;
} else if (DEVICE_ATTR_IS(pp_power_profile_mode)) {
if (amdgpu_dpm_get_power_profile_mode(adev, NULL) == -EOPNOTSUPP)
*states = ATTR_STATE_UNSUPPORTED;
+ else if (gc_ver == IP_VERSION(10, 3, 0) && amdgpu_sriov_vf(adev))
+ *states = ATTR_STATE_UNSUPPORTED;
}
switch (gc_ver) {
@@ -2031,6 +2034,13 @@ static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_
dev_attr->store = NULL;
}
break;
+ case IP_VERSION(10, 3, 0):
+ if (DEVICE_ATTR_IS(power_dpm_force_performance_level) &&
+ amdgpu_sriov_vf(adev)) {
+ dev_attr->attr.mode &= ~0222;
+ dev_attr->store = NULL;
+ }
+ break;
default:
break;
}
diff --git a/drivers/gpu/drm/amd/pm/inc/smu_v13_0_0_pptable.h b/drivers/gpu/drm/amd/pm/inc/smu_v13_0_0_pptable.h
new file mode 100644
index 000000000000..566a0da59e53
--- /dev/null
+++ b/drivers/gpu/drm/amd/pm/inc/smu_v13_0_0_pptable.h
@@ -0,0 +1,203 @@
+/*
+ * Copyright 2021 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef SMU_13_0_0_PPTABLE_H
+#define SMU_13_0_0_PPTABLE_H
+
+#pragma pack(push, 1)
+
+#define SMU_13_0_0_TABLE_FORMAT_REVISION 15
+
+//// POWERPLAYTABLE::ulPlatformCaps
+#define SMU_13_0_0_PP_PLATFORM_CAP_POWERPLAY 0x1 // This cap indicates whether CCC need to show Powerplay page.
+#define SMU_13_0_0_PP_PLATFORM_CAP_SBIOSPOWERSOURCE 0x2 // This cap indicates whether power source notificaiton is done by SBIOS instead of OS.
+#define SMU_13_0_0_PP_PLATFORM_CAP_HARDWAREDC 0x4 // This cap indicates whether DC mode notificaiton is done by GPIO pin directly.
+#define SMU_13_0_0_PP_PLATFORM_CAP_BACO 0x8 // This cap indicates whether board supports the BACO circuitry.
+#define SMU_13_0_0_PP_PLATFORM_CAP_MACO 0x10 // This cap indicates whether board supports the MACO circuitry.
+#define SMU_13_0_0_PP_PLATFORM_CAP_SHADOWPSTATE 0x20 // This cap indicates whether board supports the Shadow Pstate.
+
+// SMU_13_0_0_PP_THERMALCONTROLLER - Thermal Controller Type
+#define SMU_13_0_0_PP_THERMALCONTROLLER_NONE 0
+#define SMU_13_0_0_PP_THERMALCONTROLLER_NAVI21 28
+
+#define SMU_13_0_0_PP_OVERDRIVE_VERSION 0x81 // OverDrive 8 Table Version 0.2
+#define SMU_13_0_0_PP_POWERSAVINGCLOCK_VERSION 0x01 // Power Saving Clock Table Version 1.00
+
+enum SMU_13_0_0_ODFEATURE_CAP
+{
+ SMU_13_0_0_ODCAP_GFXCLK_LIMITS = 0,
+ SMU_13_0_0_ODCAP_GFXCLK_CURVE,
+ SMU_13_0_0_ODCAP_UCLK_LIMITS,
+ SMU_13_0_0_ODCAP_POWER_LIMIT,
+ SMU_13_0_0_ODCAP_FAN_ACOUSTIC_LIMIT,
+ SMU_13_0_0_ODCAP_FAN_SPEED_MIN,
+ SMU_13_0_0_ODCAP_TEMPERATURE_FAN,
+ SMU_13_0_0_ODCAP_TEMPERATURE_SYSTEM,
+ SMU_13_0_0_ODCAP_MEMORY_TIMING_TUNE,
+ SMU_13_0_0_ODCAP_FAN_ZERO_RPM_CONTROL,
+ SMU_13_0_0_ODCAP_AUTO_UV_ENGINE,
+ SMU_13_0_0_ODCAP_AUTO_OC_ENGINE,
+ SMU_13_0_0_ODCAP_AUTO_OC_MEMORY,
+ SMU_13_0_0_ODCAP_FAN_CURVE,
+ SMU_13_0_0_ODCAP_AUTO_FAN_ACOUSTIC_LIMIT,
+ SMU_13_0_0_ODCAP_POWER_MODE,
+ SMU_13_0_0_ODCAP_COUNT,
+};
+
+enum SMU_13_0_0_ODFEATURE_ID
+{
+ SMU_13_0_0_ODFEATURE_GFXCLK_LIMITS = 1 << SMU_13_0_0_ODCAP_GFXCLK_LIMITS, //GFXCLK Limit feature
+ SMU_13_0_0_ODFEATURE_GFXCLK_CURVE = 1 << SMU_13_0_0_ODCAP_GFXCLK_CURVE, //GFXCLK Curve feature
+ SMU_13_0_0_ODFEATURE_UCLK_LIMITS = 1 << SMU_13_0_0_ODCAP_UCLK_LIMITS, //UCLK Limit feature
+ SMU_13_0_0_ODFEATURE_POWER_LIMIT = 1 << SMU_13_0_0_ODCAP_POWER_LIMIT, //Power Limit feature
+ SMU_13_0_0_ODFEATURE_FAN_ACOUSTIC_LIMIT = 1 << SMU_13_0_0_ODCAP_FAN_ACOUSTIC_LIMIT, //Fan Acoustic RPM feature
+ SMU_13_0_0_ODFEATURE_FAN_SPEED_MIN = 1 << SMU_13_0_0_ODCAP_FAN_SPEED_MIN, //Minimum Fan Speed feature
+ SMU_13_0_0_ODFEATURE_TEMPERATURE_FAN = 1 << SMU_13_0_0_ODCAP_TEMPERATURE_FAN, //Fan Target Temperature Limit feature
+ SMU_13_0_0_ODFEATURE_TEMPERATURE_SYSTEM = 1 << SMU_13_0_0_ODCAP_TEMPERATURE_SYSTEM, //Operating Temperature Limit feature
+ SMU_13_0_0_ODFEATURE_MEMORY_TIMING_TUNE = 1 << SMU_13_0_0_ODCAP_MEMORY_TIMING_TUNE, //AC Timing Tuning feature
+ SMU_13_0_0_ODFEATURE_FAN_ZERO_RPM_CONTROL = 1 << SMU_13_0_0_ODCAP_FAN_ZERO_RPM_CONTROL, //Zero RPM feature
+ SMU_13_0_0_ODFEATURE_AUTO_UV_ENGINE = 1 << SMU_13_0_0_ODCAP_AUTO_UV_ENGINE, //Auto Under Volt GFXCLK feature
+ SMU_13_0_0_ODFEATURE_AUTO_OC_ENGINE = 1 << SMU_13_0_0_ODCAP_AUTO_OC_ENGINE, //Auto Over Clock GFXCLK feature
+ SMU_13_0_0_ODFEATURE_AUTO_OC_MEMORY = 1 << SMU_13_0_0_ODCAP_AUTO_OC_MEMORY, //Auto Over Clock MCLK feature
+ SMU_13_0_0_ODFEATURE_FAN_CURVE = 1 << SMU_13_0_0_ODCAP_FAN_CURVE, //Fan Curve feature
+ SMU_13_0_0_ODFEATURE_AUTO_FAN_ACOUSTIC_LIMIT = 1 << SMU_13_0_0_ODCAP_AUTO_FAN_ACOUSTIC_LIMIT, //Auto Fan Acoustic RPM feature
+ SMU_13_0_0_ODFEATURE_POWER_MODE = 1 << SMU_13_0_0_ODCAP_POWER_MODE, //Optimized GPU Power Mode feature
+ SMU_13_0_0_ODFEATURE_COUNT = 16,
+};
+
+#define SMU_13_0_0_MAX_ODFEATURE 32 //Maximum Number of OD Features
+
+enum SMU_13_0_0_ODSETTING_ID
+{
+ SMU_13_0_0_ODSETTING_GFXCLKFMAX = 0,
+ SMU_13_0_0_ODSETTING_GFXCLKFMIN,
+ SMU_13_0_0_ODSETTING_CUSTOM_GFX_VF_CURVE_A,
+ SMU_13_0_0_ODSETTING_CUSTOM_GFX_VF_CURVE_B,
+ SMU_13_0_0_ODSETTING_CUSTOM_GFX_VF_CURVE_C,
+ SMU_13_0_0_ODSETTING_CUSTOM_CURVE_VFT_FMIN,
+ SMU_13_0_0_ODSETTING_UCLKFMIN,
+ SMU_13_0_0_ODSETTING_UCLKFMAX,
+ SMU_13_0_0_ODSETTING_POWERPERCENTAGE,
+ SMU_13_0_0_ODSETTING_FANRPMMIN,
+ SMU_13_0_0_ODSETTING_FANRPMACOUSTICLIMIT,
+ SMU_13_0_0_ODSETTING_FANTARGETTEMPERATURE,
+ SMU_13_0_0_ODSETTING_OPERATINGTEMPMAX,
+ SMU_13_0_0_ODSETTING_ACTIMING,
+ SMU_13_0_0_ODSETTING_FAN_ZERO_RPM_CONTROL,
+ SMU_13_0_0_ODSETTING_AUTOUVENGINE,
+ SMU_13_0_0_ODSETTING_AUTOOCENGINE,
+ SMU_13_0_0_ODSETTING_AUTOOCMEMORY,
+ SMU_13_0_0_ODSETTING_FAN_CURVE_TEMPERATURE_1,
+ SMU_13_0_0_ODSETTING_FAN_CURVE_SPEED_1,
+ SMU_13_0_0_ODSETTING_FAN_CURVE_TEMPERATURE_2,
+ SMU_13_0_0_ODSETTING_FAN_CURVE_SPEED_2,
+ SMU_13_0_0_ODSETTING_FAN_CURVE_TEMPERATURE_3,
+ SMU_13_0_0_ODSETTING_FAN_CURVE_SPEED_3,
+ SMU_13_0_0_ODSETTING_FAN_CURVE_TEMPERATURE_4,
+ SMU_13_0_0_ODSETTING_FAN_CURVE_SPEED_4,
+ SMU_13_0_0_ODSETTING_FAN_CURVE_TEMPERATURE_5,
+ SMU_13_0_0_ODSETTING_FAN_CURVE_SPEED_5,
+ SMU_13_0_0_ODSETTING_AUTO_FAN_ACOUSTIC_LIMIT,
+ SMU_13_0_0_ODSETTING_POWER_MODE,
+ SMU_13_0_0_ODSETTING_COUNT,
+};
+#define SMU_13_0_0_MAX_ODSETTING 64 //Maximum Number of ODSettings
+
+enum SMU_13_0_0_PWRMODE_SETTING
+{
+ SMU_13_0_0_PMSETTING_POWER_LIMIT_QUIET = 0,
+ SMU_13_0_0_PMSETTING_POWER_LIMIT_BALANCE,
+ SMU_13_0_0_PMSETTING_POWER_LIMIT_TURBO,
+ SMU_13_0_0_PMSETTING_POWER_LIMIT_RAGE,
+ SMU_13_0_0_PMSETTING_ACOUSTIC_TEMP_QUIET,
+ SMU_13_0_0_PMSETTING_ACOUSTIC_TEMP_BALANCE,
+ SMU_13_0_0_PMSETTING_ACOUSTIC_TEMP_TURBO,
+ SMU_13_0_0_PMSETTING_ACOUSTIC_TEMP_RAGE,
+ SMU_13_0_0_PMSETTING_ACOUSTIC_TARGET_RPM_QUIET,
+ SMU_13_0_0_PMSETTING_ACOUSTIC_TARGET_RPM_BALANCE,
+ SMU_13_0_0_PMSETTING_ACOUSTIC_TARGET_RPM_TURBO,
+ SMU_13_0_0_PMSETTING_ACOUSTIC_TARGET_RPM_RAGE,
+ SMU_13_0_0_PMSETTING_ACOUSTIC_LIMIT_RPM_QUIET,
+ SMU_13_0_0_PMSETTING_ACOUSTIC_LIMIT_RPM_BALANCE,
+ SMU_13_0_0_PMSETTING_ACOUSTIC_LIMIT_RPM_TURBO,
+ SMU_13_0_0_PMSETTING_ACOUSTIC_LIMIT_RPM_RAGE,
+};
+#define SMU_13_0_0_MAX_PMSETTING 32 //Maximum Number of PowerMode Settings
+
+struct smu_13_0_0_overdrive_table
+{
+ uint8_t revision; //Revision = SMU_13_0_0_PP_OVERDRIVE_VERSION
+ uint8_t reserve[3]; //Zero filled field reserved for future use
+ uint32_t feature_count; //Total number of supported features
+ uint32_t setting_count; //Total number of supported settings
+ uint8_t cap[SMU_13_0_0_MAX_ODFEATURE]; //OD feature support flags
+ uint32_t max[SMU_13_0_0_MAX_ODSETTING]; //default maximum settings
+ uint32_t min[SMU_13_0_0_MAX_ODSETTING]; //default minimum settings
+ int16_t pm_setting[SMU_13_0_0_MAX_PMSETTING]; //Optimized power mode feature settings
+};
+
+enum SMU_13_0_0_PPCLOCK_ID
+{
+ SMU_13_0_0_PPCLOCK_GFXCLK = 0,
+ SMU_13_0_0_PPCLOCK_SOCCLK,
+ SMU_13_0_0_PPCLOCK_UCLK,
+ SMU_13_0_0_PPCLOCK_FCLK,
+ SMU_13_0_0_PPCLOCK_DCLK_0,
+ SMU_13_0_0_PPCLOCK_VCLK_0,
+ SMU_13_0_0_PPCLOCK_DCLK_1,
+ SMU_13_0_0_PPCLOCK_VCLK_1,
+ SMU_13_0_0_PPCLOCK_DCEFCLK,
+ SMU_13_0_0_PPCLOCK_DISPCLK,
+ SMU_13_0_0_PPCLOCK_PIXCLK,
+ SMU_13_0_0_PPCLOCK_PHYCLK,
+ SMU_13_0_0_PPCLOCK_DTBCLK,
+ SMU_13_0_0_PPCLOCK_COUNT,
+};
+#define SMU_13_0_0_MAX_PPCLOCK 16 //Maximum Number of PP Clocks
+
+struct smu_13_0_0_powerplay_table
+{
+ struct atom_common_table_header header; //For SMU13, header.format_revision = 15, header.content_revision = 0
+ uint8_t table_revision; //For SMU13, table_revision = 2
+ uint8_t padding;
+ uint16_t table_size; //Driver portion table size. The offset to smc_pptable including header size
+ uint32_t golden_pp_id; //PPGen use only: PP Table ID on the Golden Data Base
+ uint32_t golden_revision; //PPGen use only: PP Table Revision on the Golden Data Base
+ uint16_t format_id; //PPGen use only: PPTable for different ASICs. For SMU13 this should be 0x80
+ uint32_t platform_caps; //POWERPLAYABLE::ulPlatformCaps
+
+ uint8_t thermal_controller_type; //one of SMU_13_0_0_PP_THERMALCONTROLLER
+
+ uint16_t small_power_limit1;
+ uint16_t small_power_limit2;
+ uint16_t boost_power_limit; //For Gemini Board, when the slave adapter is in BACO mode, the master adapter will use this boost power limit instead of the default power limit to boost the power limit.
+ uint16_t software_shutdown_temp;
+
+ uint32_t reserve[45];
+
+ struct smu_13_0_0_overdrive_table overdrive_table;
+ uint8_t padding1;
+ PPTable_t smc_pptable; //PPTable_t in driver_if.h
+};
+
+#pragma pack(pop)
+
+#endif
diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
index f1544755d8b4..6016b325b6b5 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
@@ -37,7 +37,10 @@
#include "aldebaran_ppt.h"
#include "yellow_carp_ppt.h"
#include "cyan_skillfish_ppt.h"
+#include "smu_v13_0_0_ppt.h"
+#include "smu_v13_0_4_ppt.h"
#include "smu_v13_0_5_ppt.h"
+#include "smu_v13_0_7_ppt.h"
#include "amd_pcie.h"
/*
@@ -488,8 +491,20 @@ static int smu_sys_set_pp_table(void *handle,
static int smu_get_driver_allowed_feature_mask(struct smu_context *smu)
{
struct smu_feature *feature = &smu->smu_feature;
- int ret = 0;
uint32_t allowed_feature_mask[SMU_FEATURE_MAX/32];
+ int ret = 0;
+
+ /*
+ * With SCPM enabled, the allowed featuremasks setting(via
+ * PPSMC_MSG_SetAllowedFeaturesMaskLow/High) is not permitted.
+ * That means there is no way to let PMFW knows the settings below.
+ * Thus, we just assume all the features are allowed under
+ * such scenario.
+ */
+ if (smu->adev->scpm_enabled) {
+ bitmap_fill(feature->allowed, SMU_FEATURE_MAX);
+ return 0;
+ }
bitmap_zero(feature->allowed, SMU_FEATURE_MAX);
@@ -536,6 +551,9 @@ static int smu_set_funcs(struct amdgpu_device *adev)
case IP_VERSION(13, 0, 8):
yellow_carp_set_ppt_funcs(smu);
break;
+ case IP_VERSION(13, 0, 4):
+ smu_v13_0_4_set_ppt_funcs(smu);
+ break;
case IP_VERSION(13, 0, 5):
smu_v13_0_5_set_ppt_funcs(smu);
break;
@@ -553,6 +571,12 @@ static int smu_set_funcs(struct amdgpu_device *adev)
/* Enable pp_od_clk_voltage node */
smu->od_enabled = true;
break;
+ case IP_VERSION(13, 0, 0):
+ smu_v13_0_0_set_ppt_funcs(smu);
+ break;
+ case IP_VERSION(13, 0, 7):
+ smu_v13_0_7_set_ppt_funcs(smu);
+ break;
default:
return -EINVAL;
}
@@ -576,6 +600,8 @@ static int smu_early_init(void *handle)
smu->smu_baco.platform_support = false;
smu->user_dpm_profile.fan_mode = -1;
+ mutex_init(&smu->message_lock);
+
adev->powerplay.pp_handle = smu;
adev->powerplay.pp_funcs = &swsmu_pm_funcs;
@@ -975,8 +1001,6 @@ static int smu_sw_init(void *handle)
bitmap_zero(smu->smu_feature.supported, SMU_FEATURE_MAX);
bitmap_zero(smu->smu_feature.allowed, SMU_FEATURE_MAX);
- mutex_init(&smu->message_lock);
-
INIT_WORK(&smu->throttling_logging_work, smu_throttling_logging_work_fn);
INIT_WORK(&smu->interrupt_work, smu_interrupt_work_fn);
atomic64_set(&smu->throttle_int_counter, 0);
@@ -1020,6 +1044,19 @@ static int smu_sw_init(void *handle)
return ret;
}
+ /* get boot_values from vbios to set revision, gfxclk, and etc. */
+ ret = smu_get_vbios_bootup_values(smu);
+ if (ret) {
+ dev_err(adev->dev, "Failed to get VBIOS boot clock values!\n");
+ return ret;
+ }
+
+ ret = smu_init_pptable_microcode(smu);
+ if (ret) {
+ dev_err(adev->dev, "Failed to setup pptable firmware!\n");
+ return ret;
+ }
+
ret = smu_register_irq_handler(smu);
if (ret) {
dev_err(adev->dev, "Failed to register smc irq handler!\n");
@@ -1134,15 +1171,28 @@ static int smu_smc_hw_setup(struct smu_context *smu)
return ret;
}
+ ret = smu_setup_pptable(smu);
+ if (ret) {
+ dev_err(adev->dev, "Failed to setup pptable!\n");
+ return ret;
+ }
+
/* smu_dump_pptable(smu); */
+
/*
- * Copy pptable bo in the vram to smc with SMU MSGs such as
- * SetDriverDramAddr and TransferTableDram2Smu.
+ * With SCPM enabled, PSP is responsible for the PPTable transferring
+ * (to SMU). Driver involvement is not needed and permitted.
*/
- ret = smu_write_pptable(smu);
- if (ret) {
- dev_err(adev->dev, "Failed to transfer pptable to SMC!\n");
- return ret;
+ if (!adev->scpm_enabled) {
+ /*
+ * Copy pptable bo in the vram to smc with SMU MSGs such as
+ * SetDriverDramAddr and TransferTableDram2Smu.
+ */
+ ret = smu_write_pptable(smu);
+ if (ret) {
+ dev_err(adev->dev, "Failed to transfer pptable to SMC!\n");
+ return ret;
+ }
}
/* issue Run*Btc msg */
@@ -1150,10 +1200,16 @@ static int smu_smc_hw_setup(struct smu_context *smu)
if (ret)
return ret;
- ret = smu_feature_set_allowed_mask(smu);
- if (ret) {
- dev_err(adev->dev, "Failed to set driver allowed features mask!\n");
- return ret;
+ /*
+ * With SCPM enabled, these actions(and relevant messages) are
+ * not needed and permitted.
+ */
+ if (!adev->scpm_enabled) {
+ ret = smu_feature_set_allowed_mask(smu);
+ if (ret) {
+ dev_err(adev->dev, "Failed to set driver allowed features mask!\n");
+ return ret;
+ }
}
ret = smu_system_features_control(smu, true);
@@ -1174,6 +1230,17 @@ static int smu_smc_hw_setup(struct smu_context *smu)
if (!smu_is_dpm_running(smu))
dev_info(adev->dev, "dpm has been disabled\n");
+ /*
+ * Set initialized values (get from vbios) to dpm tables context such as
+ * gfxclk, memclk, dcefclk, and etc. And enable the DPM feature for each
+ * type of clks.
+ */
+ ret = smu_set_default_dpm_table(smu);
+ if (ret) {
+ dev_err(adev->dev, "Failed to setup default dpm clock tables!\n");
+ return ret;
+ }
+
if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN4)
pcie_gen = 3;
else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3)
@@ -1217,17 +1284,6 @@ static int smu_smc_hw_setup(struct smu_context *smu)
return ret;
}
- /*
- * Set initialized values (get from vbios) to dpm tables context such as
- * gfxclk, memclk, dcefclk, and etc. And enable the DPM feature for each
- * type of clks.
- */
- ret = smu_set_default_dpm_table(smu);
- if (ret) {
- dev_err(adev->dev, "Failed to setup default dpm clock tables!\n");
- return ret;
- }
-
ret = smu_notify_display_change(smu);
if (ret) {
dev_err(adev->dev, "Failed to notify display change!\n");
@@ -1304,19 +1360,6 @@ static int smu_hw_init(void *handle)
if (!smu->pm_enabled)
return 0;
- /* get boot_values from vbios to set revision, gfxclk, and etc. */
- ret = smu_get_vbios_bootup_values(smu);
- if (ret) {
- dev_err(adev->dev, "Failed to get VBIOS boot clock values!\n");
- return ret;
- }
-
- ret = smu_setup_pptable(smu);
- if (ret) {
- dev_err(adev->dev, "Failed to setup pptable!\n");
- return ret;
- }
-
ret = smu_get_driver_allowed_feature_mask(smu);
if (ret)
return ret;
@@ -1351,14 +1394,8 @@ static int smu_disable_dpms(struct smu_context *smu)
{
struct amdgpu_device *adev = smu->adev;
int ret = 0;
- /*
- * TODO: (adev->in_suspend && !adev->in_s0ix) is added to pair
- * the workaround which always reset the asic in suspend.
- * It's likely that workaround will be dropped in the future.
- * Then the change here should be dropped together.
- */
bool use_baco = !smu->is_apu &&
- (((amdgpu_in_reset(adev) || (adev->in_suspend && !adev->in_s0ix)) &&
+ ((amdgpu_in_reset(adev) &&
(amdgpu_asic_reset_method(adev) == AMD_RESET_METHOD_BACO)) ||
((adev->in_runpm || adev->in_s4) && amdgpu_asic_supports_baco(adev)));
@@ -1415,9 +1452,12 @@ static int smu_disable_dpms(struct smu_context *smu)
if (ret)
dev_err(adev->dev, "Failed to disable smu features except BACO.\n");
} else {
- ret = smu_system_features_control(smu, false);
- if (ret)
- dev_err(adev->dev, "Failed to disable smu features.\n");
+ /* DisableAllSmuFeatures message is not permitted with SCPM enabled */
+ if (!adev->scpm_enabled) {
+ ret = smu_system_features_control(smu, false);
+ if (ret)
+ dev_err(adev->dev, "Failed to disable smu features.\n");
+ }
}
if (adev->ip_versions[GC_HWIP][0] >= IP_VERSION(9, 4, 2) &&
@@ -3031,7 +3071,7 @@ void amdgpu_smu_stb_debug_fs_init(struct amdgpu_device *adev)
struct smu_context *smu = adev->powerplay.pp_handle;
- if (!smu->stb_context.stb_buf_size)
+ if (!smu || (!smu->stb_context.stb_buf_size))
return;
debugfs_create_file_size("amdgpu_smu_stb_dump",
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
index 46e34ed8a3c8..a6a7b6c33683 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
@@ -27,6 +27,7 @@
#include "dm_pp_interface.h"
#include "dm_pp_smu.h"
#include "smu_types.h"
+#include "linux/firmware.h"
#define SMU_THERMAL_MINIMUM_ALERT_TEMP 0
#define SMU_THERMAL_MAXIMUM_ALERT_TEMP 255
@@ -320,6 +321,7 @@ enum smu_table_id
SMU_TABLE_I2C_COMMANDS,
SMU_TABLE_PACE,
SMU_TABLE_ECCINFO,
+ SMU_TABLE_COMBO_PPTABLE,
SMU_TABLE_COUNT,
};
@@ -335,7 +337,8 @@ struct smu_table_context
void *max_sustainable_clocks;
struct smu_bios_boot_up_values boot_values;
- void *driver_pptable;
+ void *driver_pptable;
+ void *combo_pptable;
void *ecc_table;
void *driver_smu_config_table;
struct smu_table tables[SMU_TABLE_COUNT];
@@ -451,6 +454,7 @@ struct smu_umd_pstate_table {
struct pstates_clk_freq uclk_pstate;
struct pstates_clk_freq vclk_pstate;
struct pstates_clk_freq dclk_pstate;
+ struct pstates_clk_freq fclk_pstate;
};
struct cmn2asic_msg_mapping {
@@ -557,6 +561,8 @@ struct smu_context
struct smu_user_dpm_profile user_dpm_profile;
struct stb_context stb_context;
+
+ struct firmware pptable_firmware;
};
struct i2c_adapter;
@@ -1298,6 +1304,11 @@ struct pptable_funcs {
* of SMUBUS table.
*/
int (*send_hbm_bad_channel_flag)(struct smu_context *smu, uint32_t size);
+
+ /**
+ * @init_pptable_microcode: Prepare the pptable microcode to upload via PSP
+ */
+ int (*init_pptable_microcode)(struct smu_context *smu);
};
typedef enum {
@@ -1317,6 +1328,8 @@ typedef enum {
METRICS_AVERAGE_UCLK,
METRICS_AVERAGE_VCLK,
METRICS_AVERAGE_DCLK,
+ METRICS_AVERAGE_VCLK1,
+ METRICS_AVERAGE_DCLK1,
METRICS_AVERAGE_GFXACTIVITY,
METRICS_AVERAGE_MEMACTIVITY,
METRICS_AVERAGE_VCNACTIVITY,
@@ -1335,6 +1348,9 @@ typedef enum {
METRICS_SS_DGPU_SHARE,
METRICS_UNIQUE_ID_UPPER32,
METRICS_UNIQUE_ID_LOWER32,
+ METRICS_PCIE_RATE,
+ METRICS_PCIE_WIDTH,
+ METRICS_CURR_FANPWM,
} MetricsMember_t;
enum smu_cmn2asic_mapping_type {
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu11_driver_if_sienna_cichlid.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu11_driver_if_sienna_cichlid.h
index 08f0bb2af5d2..351a4af429b3 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu11_driver_if_sienna_cichlid.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu11_driver_if_sienna_cichlid.h
@@ -1541,10 +1541,73 @@ typedef struct {
} SmuMetrics_V3_t;
typedef struct {
+ uint32_t CurrClock[PPCLK_COUNT];
+
+ uint16_t AverageGfxclkFrequencyPreDs;
+ uint16_t AverageGfxclkFrequencyPostDs;
+ uint16_t AverageFclkFrequencyPreDs;
+ uint16_t AverageFclkFrequencyPostDs;
+ uint16_t AverageUclkFrequencyPreDs;
+ uint16_t AverageUclkFrequencyPostDs;
+
+
+ uint16_t AverageGfxActivity;
+ uint16_t AverageUclkActivity;
+ uint8_t CurrSocVoltageOffset;
+ uint8_t CurrGfxVoltageOffset;
+ uint8_t CurrMemVidOffset;
+ uint8_t Padding8;
+ uint16_t AverageSocketPower;
+ uint16_t TemperatureEdge;
+ uint16_t TemperatureHotspot;
+ uint16_t TemperatureMem;
+ uint16_t TemperatureVrGfx;
+ uint16_t TemperatureVrMem0;
+ uint16_t TemperatureVrMem1;
+ uint16_t TemperatureVrSoc;
+ uint16_t TemperatureLiquid0;
+ uint16_t TemperatureLiquid1;
+ uint16_t TemperaturePlx;
+ uint16_t Padding16;
+ uint32_t AccCnt;
+ uint8_t ThrottlingPercentage[THROTTLER_COUNT];
+
+
+ uint8_t LinkDpmLevel;
+ uint8_t CurrFanPwm;
+ uint16_t CurrFanSpeed;
+
+ //BACO metrics, PMFW-1721
+ //metrics for D3hot entry/exit and driver ARM msgs
+ uint8_t D3HotEntryCountPerMode[D3HOT_SEQUENCE_COUNT];
+ uint8_t D3HotExitCountPerMode[D3HOT_SEQUENCE_COUNT];
+ uint8_t ArmMsgReceivedCountPerMode[D3HOT_SEQUENCE_COUNT];
+
+ //PMFW-4362
+ uint32_t EnergyAccumulator;
+ uint16_t AverageVclk0Frequency;
+ uint16_t AverageDclk0Frequency;
+ uint16_t AverageVclk1Frequency;
+ uint16_t AverageDclk1Frequency;
+ uint16_t VcnUsagePercentage0;
+ uint16_t VcnUsagePercentage1;
+ uint8_t PcieRate;
+ uint8_t PcieWidth;
+ uint16_t AverageGfxclkFrequencyTarget;
+
+ uint8_t ApuSTAPMSmartShiftLimit;
+ uint8_t AverageApuSocketPower;
+ uint8_t ApuSTAPMLimit;
+ uint8_t Padding8_2;
+
+} SmuMetrics_V4_t;
+
+typedef struct {
union {
SmuMetrics_t SmuMetrics;
SmuMetrics_V2_t SmuMetrics_V2;
SmuMetrics_V3_t SmuMetrics_V3;
+ SmuMetrics_V4_t SmuMetrics_V4;
};
uint32_t Spare[1];
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_0.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_0.h
new file mode 100644
index 000000000000..ecc6411dfc8d
--- /dev/null
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_0.h
@@ -0,0 +1,1544 @@
+/*
+ * Copyright 2021 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef SMU13_DRIVER_IF_V13_0_0_H
+#define SMU13_DRIVER_IF_V13_0_0_H
+
+// *** IMPORTANT ***
+// PMFW TEAM: Always increment the interface version on any change to this file
+#define SMU13_DRIVER_IF_VERSION 0x23
+
+//Increment this version if SkuTable_t or BoardTable_t change
+#define PPTABLE_VERSION 0x1D
+
+#define NUM_GFXCLK_DPM_LEVELS 16
+#define NUM_SOCCLK_DPM_LEVELS 8
+#define NUM_MP0CLK_DPM_LEVELS 2
+#define NUM_DCLK_DPM_LEVELS 8
+#define NUM_VCLK_DPM_LEVELS 8
+#define NUM_DISPCLK_DPM_LEVELS 8
+#define NUM_DPPCLK_DPM_LEVELS 8
+#define NUM_DPREFCLK_DPM_LEVELS 8
+#define NUM_DCFCLK_DPM_LEVELS 8
+#define NUM_DTBCLK_DPM_LEVELS 8
+#define NUM_UCLK_DPM_LEVELS 4
+#define NUM_LINK_LEVELS 3
+#define NUM_FCLK_DPM_LEVELS 8
+#define NUM_OD_FAN_MAX_POINTS 6
+
+// Feature Control Defines
+#define FEATURE_FW_DATA_READ_BIT 0
+#define FEATURE_DPM_GFXCLK_BIT 1
+#define FEATURE_DPM_GFX_POWER_OPTIMIZER_BIT 2
+#define FEATURE_DPM_UCLK_BIT 3
+#define FEATURE_DPM_FCLK_BIT 4
+#define FEATURE_DPM_SOCCLK_BIT 5
+#define FEATURE_DPM_MP0CLK_BIT 6
+#define FEATURE_DPM_LINK_BIT 7
+#define FEATURE_DPM_DCN_BIT 8
+#define FEATURE_VMEMP_SCALING_BIT 9
+#define FEATURE_VDDIO_MEM_SCALING_BIT 10
+#define FEATURE_DS_GFXCLK_BIT 11
+#define FEATURE_DS_SOCCLK_BIT 12
+#define FEATURE_DS_FCLK_BIT 13
+#define FEATURE_DS_LCLK_BIT 14
+#define FEATURE_DS_DCFCLK_BIT 15
+#define FEATURE_DS_UCLK_BIT 16
+#define FEATURE_GFX_ULV_BIT 17
+#define FEATURE_FW_DSTATE_BIT 18
+#define FEATURE_GFXOFF_BIT 19
+#define FEATURE_BACO_BIT 20
+#define FEATURE_MM_DPM_BIT 21
+#define FEATURE_SOC_MPCLK_DS_BIT 22
+#define FEATURE_BACO_MPCLK_DS_BIT 23
+#define FEATURE_THROTTLERS_BIT 24
+#define FEATURE_SMARTSHIFT_BIT 25
+#define FEATURE_GTHR_BIT 26
+#define FEATURE_ACDC_BIT 27
+#define FEATURE_VR0HOT_BIT 28
+#define FEATURE_FW_CTF_BIT 29
+#define FEATURE_FAN_CONTROL_BIT 30
+#define FEATURE_GFX_DCS_BIT 31
+#define FEATURE_GFX_READ_MARGIN_BIT 32
+#define FEATURE_LED_DISPLAY_BIT 33
+#define FEATURE_GFXCLK_SPREAD_SPECTRUM_BIT 34
+#define FEATURE_OUT_OF_BAND_MONITOR_BIT 35
+#define FEATURE_OPTIMIZED_VMIN_BIT 36
+#define FEATURE_GFX_IMU_BIT 37
+#define FEATURE_BOOT_TIME_CAL_BIT 38
+#define FEATURE_GFX_PCC_DFLL_BIT 39
+#define FEATURE_SOC_CG_BIT 40
+#define FEATURE_DF_CSTATE_BIT 41
+#define FEATURE_GFX_EDC_BIT 42
+#define FEATURE_BOOT_POWER_OPT_BIT 43
+#define FEATURE_CLOCK_POWER_DOWN_BYPASS_BIT 44
+#define FEATURE_DS_VCN_BIT 45
+#define FEATURE_BACO_CG_BIT 46
+#define FEATURE_MEM_TEMP_READ_BIT 47
+#define FEATURE_ATHUB_MMHUB_PG_BIT 48
+#define FEATURE_SOC_PCC_BIT 49
+#define FEATURE_SPARE_50_BIT 50
+#define FEATURE_SPARE_51_BIT 51
+#define FEATURE_SPARE_52_BIT 52
+#define FEATURE_SPARE_53_BIT 53
+#define FEATURE_SPARE_54_BIT 54
+#define FEATURE_SPARE_55_BIT 55
+#define FEATURE_SPARE_56_BIT 56
+#define FEATURE_SPARE_57_BIT 57
+#define FEATURE_SPARE_58_BIT 58
+#define FEATURE_SPARE_59_BIT 59
+#define FEATURE_SPARE_60_BIT 60
+#define FEATURE_SPARE_61_BIT 61
+#define FEATURE_SPARE_62_BIT 62
+#define FEATURE_SPARE_63_BIT 63
+#define NUM_FEATURES 64
+
+//For use with feature control messages
+typedef enum {
+ FEATURE_PWR_ALL,
+ FEATURE_PWR_S5,
+ FEATURE_PWR_BACO,
+ FEATURE_PWR_SOC,
+ FEATURE_PWR_GFX,
+ FEATURE_PWR_DOMAIN_COUNT,
+} FEATURE_PWR_DOMAIN_e;
+
+
+// Debug Overrides Bitmask
+#define DEBUG_OVERRIDE_DISABLE_VOLT_LINK_VCN_FCLK 0x00000001
+#define DEBUG_OVERRIDE_DISABLE_VOLT_LINK_DCN_FCLK 0x00000002
+#define DEBUG_OVERRIDE_DISABLE_VOLT_LINK_MP0_FCLK 0x00000004
+#define DEBUG_OVERRIDE_DISABLE_VOLT_LINK_VCN_DCFCLK 0x00000008
+#define DEBUG_OVERRIDE_DISABLE_FAST_FCLK_TIMER 0x00000010
+#define DEBUG_OVERRIDE_DISABLE_VCN_PG 0x00000020
+#define DEBUG_OVERRIDE_DISABLE_FMAX_VMAX 0x00000040
+#define DEBUG_OVERRIDE_DISABLE_IMU_FW_CHECKS 0x00000080
+#define DEBUG_OVERRIDE_DISABLE_D0i2_REENTRY_HSR_TIMER_CHECK 0x00000100
+#define DEBUG_OVERRIDE_DISABLE_DFLL 0x00000200
+#define DEBUG_OVERRIDE_ENABLE_RLC_VF_BRINGUP_MODE 0x00000400
+#define DEBUG_OVERRIDE_DFLL_MASTER_MODE 0x00000800
+
+// VR Mapping Bit Defines
+#define VR_MAPPING_VR_SELECT_MASK 0x01
+#define VR_MAPPING_VR_SELECT_SHIFT 0x00
+
+#define VR_MAPPING_PLANE_SELECT_MASK 0x02
+#define VR_MAPPING_PLANE_SELECT_SHIFT 0x01
+
+// PSI Bit Defines
+#define PSI_SEL_VR0_PLANE0_PSI0 0x01
+#define PSI_SEL_VR0_PLANE0_PSI1 0x02
+#define PSI_SEL_VR0_PLANE1_PSI0 0x04
+#define PSI_SEL_VR0_PLANE1_PSI1 0x08
+#define PSI_SEL_VR1_PLANE0_PSI0 0x10
+#define PSI_SEL_VR1_PLANE0_PSI1 0x20
+#define PSI_SEL_VR1_PLANE1_PSI0 0x40
+#define PSI_SEL_VR1_PLANE1_PSI1 0x80
+
+typedef enum {
+ SVI_PSI_0, // Full phase count (default)
+ SVI_PSI_1, // Phase count 1st level
+ SVI_PSI_2, // Phase count 2nd level
+ SVI_PSI_3, // Single phase operation + active diode emulation
+ SVI_PSI_4, // Single phase operation + passive diode emulation *optional*
+ SVI_PSI_5, // Reserved
+ SVI_PSI_6, // Power down to 0V (voltage regulation disabled)
+ SVI_PSI_7, // Automated phase shedding and diode emulation
+} SVI_PSI_e;
+
+// Throttler Control/Status Bits
+#define THROTTLER_TEMP_EDGE_BIT 0
+#define THROTTLER_TEMP_HOTSPOT_BIT 1
+#define THROTTLER_TEMP_HOTSPOT_G_BIT 2
+#define THROTTLER_TEMP_HOTSPOT_M_BIT 3
+#define THROTTLER_TEMP_MEM_BIT 4
+#define THROTTLER_TEMP_VR_GFX_BIT 5
+#define THROTTLER_TEMP_VR_MEM0_BIT 6
+#define THROTTLER_TEMP_VR_MEM1_BIT 7
+#define THROTTLER_TEMP_VR_SOC_BIT 8
+#define THROTTLER_TEMP_VR_U_BIT 9
+#define THROTTLER_TEMP_LIQUID0_BIT 10
+#define THROTTLER_TEMP_LIQUID1_BIT 11
+#define THROTTLER_TEMP_PLX_BIT 12
+#define THROTTLER_TDC_GFX_BIT 13
+#define THROTTLER_TDC_SOC_BIT 14
+#define THROTTLER_TDC_U_BIT 15
+#define THROTTLER_PPT0_BIT 16
+#define THROTTLER_PPT1_BIT 17
+#define THROTTLER_PPT2_BIT 18
+#define THROTTLER_PPT3_BIT 19
+#define THROTTLER_FIT_BIT 20
+#define THROTTLER_GFX_APCC_PLUS_BIT 21
+#define THROTTLER_COUNT 22
+
+// FW DState Features Control Bits
+#define FW_DSTATE_SOC_ULV_BIT 0
+#define FW_DSTATE_G6_HSR_BIT 1
+#define FW_DSTATE_G6_PHY_VMEMP_OFF_BIT 2
+#define FW_DSTATE_SMN_DS_BIT 3
+#define FW_DSTATE_MP1_WHISPER_MODE_BIT 4
+#define FW_DSTATE_SOC_LIV_MIN_BIT 5
+#define FW_DSTATE_SOC_PLL_PWRDN_BIT 6
+#define FW_DSTATE_MEM_PLL_PWRDN_BIT 7
+#define FW_DSTATE_MALL_ALLOC_BIT 8
+#define FW_DSTATE_MEM_PSI_BIT 9
+#define FW_DSTATE_HSR_NON_STROBE_BIT 10
+#define FW_DSTATE_MP0_ENTER_WFI_BIT 11
+#define FW_DSTATE_U_ULV_BIT 12
+#define FW_DSTATE_MALL_FLUSH_BIT 13
+#define FW_DSTATE_SOC_PSI_BIT 14
+#define FW_DSTATE_U_PSI_BIT 15
+#define FW_DSTATE_UCP_DS_BIT 16
+#define FW_DSTATE_CSRCLK_DS_BIT 17
+#define FW_DSTATE_MMHUB_INTERLOCK_BIT 18
+#define FW_DSTATE_D0i3_2_QUIET_FW_BIT 19
+#define FW_DSTATE_CLDO_PRG_BIT 20
+#define FW_DSTATE_DF_PLL_PWRDN_BIT 21
+#define FW_DSTATE_U_LOW_PWR_MODE_EN_BIT 22
+#define FW_DSTATE_GFX_PSI6_BIT 23
+#define FW_DSTATE_GFX_VR_PWR_STAGE_BIT 24
+
+//LED Display Mask & Control Bits
+#define LED_DISPLAY_GFX_DPM_BIT 0
+#define LED_DISPLAY_PCIE_BIT 1
+#define LED_DISPLAY_ERROR_BIT 2
+
+
+#define MEM_TEMP_READ_OUT_OF_BAND_BIT 0
+#define MEM_TEMP_READ_IN_BAND_REFRESH_BIT 1
+#define MEM_TEMP_READ_IN_BAND_DUMMY_PSTATE_BIT 2
+
+typedef enum {
+ SMARTSHIFT_VERSION_1,
+ SMARTSHIFT_VERSION_2,
+ SMARTSHIFT_VERSION_3,
+} SMARTSHIFT_VERSION_e;
+
+typedef enum {
+ FOPT_CALC_AC_CALC_DC,
+ FOPT_PPTABLE_AC_CALC_DC,
+ FOPT_CALC_AC_PPTABLE_DC,
+ FOPT_PPTABLE_AC_PPTABLE_DC,
+} FOPT_CALC_e;
+
+typedef enum {
+ DRAM_BIT_WIDTH_DISABLED = 0,
+ DRAM_BIT_WIDTH_X_8 = 8,
+ DRAM_BIT_WIDTH_X_16 = 16,
+ DRAM_BIT_WIDTH_X_32 = 32,
+ DRAM_BIT_WIDTH_X_64 = 64,
+ DRAM_BIT_WIDTH_X_128 = 128,
+ DRAM_BIT_WIDTH_COUNT,
+} DRAM_BIT_WIDTH_TYPE_e;
+
+//I2C Interface
+#define NUM_I2C_CONTROLLERS 8
+
+#define I2C_CONTROLLER_ENABLED 1
+#define I2C_CONTROLLER_DISABLED 0
+
+#define MAX_SW_I2C_COMMANDS 24
+
+typedef enum {
+ I2C_CONTROLLER_PORT_0 = 0, //CKSVII2C0
+ I2C_CONTROLLER_PORT_1 = 1, //CKSVII2C1
+ I2C_CONTROLLER_PORT_COUNT,
+} I2cControllerPort_e;
+
+typedef enum {
+ I2C_CONTROLLER_NAME_VR_GFX = 0,
+ I2C_CONTROLLER_NAME_VR_SOC,
+ I2C_CONTROLLER_NAME_VR_VMEMP,
+ I2C_CONTROLLER_NAME_VR_VDDIO,
+ I2C_CONTROLLER_NAME_LIQUID0,
+ I2C_CONTROLLER_NAME_LIQUID1,
+ I2C_CONTROLLER_NAME_PLX,
+ I2C_CONTROLLER_NAME_OTHER,
+ I2C_CONTROLLER_NAME_COUNT,
+} I2cControllerName_e;
+
+typedef enum {
+ I2C_CONTROLLER_THROTTLER_TYPE_NONE = 0,
+ I2C_CONTROLLER_THROTTLER_VR_GFX,
+ I2C_CONTROLLER_THROTTLER_VR_SOC,
+ I2C_CONTROLLER_THROTTLER_VR_VMEMP,
+ I2C_CONTROLLER_THROTTLER_VR_VDDIO,
+ I2C_CONTROLLER_THROTTLER_LIQUID0,
+ I2C_CONTROLLER_THROTTLER_LIQUID1,
+ I2C_CONTROLLER_THROTTLER_PLX,
+ I2C_CONTROLLER_THROTTLER_INA3221,
+ I2C_CONTROLLER_THROTTLER_COUNT,
+} I2cControllerThrottler_e;
+
+typedef enum {
+ I2C_CONTROLLER_PROTOCOL_VR_XPDE132G5,
+ I2C_CONTROLLER_PROTOCOL_VR_IR35217,
+ I2C_CONTROLLER_PROTOCOL_TMP_TMP102A,
+ I2C_CONTROLLER_PROTOCOL_INA3221,
+ I2C_CONTROLLER_PROTOCOL_COUNT,
+} I2cControllerProtocol_e;
+
+typedef struct {
+ uint8_t Enabled;
+ uint8_t Speed;
+ uint8_t SlaveAddress;
+ uint8_t ControllerPort;
+ uint8_t ControllerName;
+ uint8_t ThermalThrotter;
+ uint8_t I2cProtocol;
+ uint8_t PaddingConfig;
+} I2cControllerConfig_t;
+
+typedef enum {
+ I2C_PORT_SVD_SCL = 0,
+ I2C_PORT_GPIO,
+} I2cPort_e;
+
+typedef enum {
+ I2C_SPEED_FAST_50K = 0, //50 Kbits/s
+ I2C_SPEED_FAST_100K, //100 Kbits/s
+ I2C_SPEED_FAST_400K, //400 Kbits/s
+ I2C_SPEED_FAST_PLUS_1M, //1 Mbits/s (in fast mode)
+ I2C_SPEED_HIGH_1M, //1 Mbits/s (in high speed mode)
+ I2C_SPEED_HIGH_2M, //2.3 Mbits/s
+ I2C_SPEED_COUNT,
+} I2cSpeed_e;
+
+typedef enum {
+ I2C_CMD_READ = 0,
+ I2C_CMD_WRITE,
+ I2C_CMD_COUNT,
+} I2cCmdType_e;
+
+#define CMDCONFIG_STOP_BIT 0
+#define CMDCONFIG_RESTART_BIT 1
+#define CMDCONFIG_READWRITE_BIT 2 //bit should be 0 for read, 1 for write
+
+#define CMDCONFIG_STOP_MASK (1 << CMDCONFIG_STOP_BIT)
+#define CMDCONFIG_RESTART_MASK (1 << CMDCONFIG_RESTART_BIT)
+#define CMDCONFIG_READWRITE_MASK (1 << CMDCONFIG_READWRITE_BIT)
+
+typedef struct {
+ uint8_t ReadWriteData; //Return data for read. Data to send for write
+ uint8_t CmdConfig; //Includes whether associated command should have a stop or restart command, and is a read or write
+} SwI2cCmd_t; //SW I2C Command Table
+
+typedef struct {
+ uint8_t I2CcontrollerPort; //CKSVII2C0(0) or //CKSVII2C1(1)
+ uint8_t I2CSpeed; //Use I2cSpeed_e to indicate speed to select
+ uint8_t SlaveAddress; //Slave address of device
+ uint8_t NumCmds; //Number of commands
+
+ SwI2cCmd_t SwI2cCmds[MAX_SW_I2C_COMMANDS];
+} SwI2cRequest_t; // SW I2C Request Table
+
+typedef struct {
+ SwI2cRequest_t SwI2cRequest;
+
+ uint32_t Spare[8];
+ uint32_t MmHubPadding[8]; // SMU internal use
+} SwI2cRequestExternal_t;
+
+typedef struct {
+ uint64_t mca_umc_status;
+ uint64_t mca_umc_addr;
+
+ uint16_t ce_count_lo_chip;
+ uint16_t ce_count_hi_chip;
+
+ uint32_t eccPadding;
+} EccInfo_t;
+
+typedef struct {
+ EccInfo_t EccInfo[24];
+} EccInfoTable_t;
+
+//D3HOT sequences
+typedef enum {
+ BACO_SEQUENCE,
+ MSR_SEQUENCE,
+ BAMACO_SEQUENCE,
+ ULPS_SEQUENCE,
+ D3HOT_SEQUENCE_COUNT,
+} D3HOTSequence_e;
+
+//This is aligned with RSMU PGFSM Register Mapping
+typedef enum {
+ PG_DYNAMIC_MODE = 0,
+ PG_STATIC_MODE,
+} PowerGatingMode_e;
+
+//This is aligned with RSMU PGFSM Register Mapping
+typedef enum {
+ PG_POWER_DOWN = 0,
+ PG_POWER_UP,
+} PowerGatingSettings_e;
+
+typedef struct {
+ uint32_t a; // store in IEEE float format in this variable
+ uint32_t b; // store in IEEE float format in this variable
+ uint32_t c; // store in IEEE float format in this variable
+} QuadraticInt_t;
+
+typedef struct {
+ uint32_t m; // store in IEEE float format in this variable
+ uint32_t b; // store in IEEE float format in this variable
+} LinearInt_t;
+
+typedef struct {
+ uint32_t a; // store in IEEE float format in this variable
+ uint32_t b; // store in IEEE float format in this variable
+ uint32_t c; // store in IEEE float format in this variable
+} DroopInt_t;
+
+typedef enum {
+ DCS_ARCH_DISABLED,
+ DCS_ARCH_FADCS,
+ DCS_ARCH_ASYNC,
+} DCS_ARCH_e;
+
+//Only Clks that have DPM descriptors are listed here
+typedef enum {
+ PPCLK_GFXCLK = 0,
+ PPCLK_SOCCLK,
+ PPCLK_UCLK,
+ PPCLK_FCLK,
+ PPCLK_DCLK_0,
+ PPCLK_VCLK_0,
+ PPCLK_DCLK_1,
+ PPCLK_VCLK_1,
+ PPCLK_DISPCLK,
+ PPCLK_DPPCLK,
+ PPCLK_DPREFCLK,
+ PPCLK_DCFCLK,
+ PPCLK_DTBCLK,
+ PPCLK_COUNT,
+} PPCLK_e;
+
+typedef enum {
+ VOLTAGE_MODE_PPTABLE = 0,
+ VOLTAGE_MODE_FUSES,
+ VOLTAGE_MODE_COUNT,
+} VOLTAGE_MODE_e;
+
+
+typedef enum {
+ AVFS_VOLTAGE_GFX = 0,
+ AVFS_VOLTAGE_SOC,
+ AVFS_VOLTAGE_COUNT,
+} AVFS_VOLTAGE_TYPE_e;
+
+typedef enum {
+ AVFS_TEMP_COLD = 0,
+ AVFS_TEMP_HOT,
+ AVFS_TEMP_COUNT,
+} AVFS_TEMP_e;
+
+typedef enum {
+ AVFS_D_G,
+ AVFS_D_M_B,
+ AVFS_D_M_S,
+ AVFS_D_COUNT,
+} AVFS_D_e;
+
+typedef enum {
+ UCLK_DIV_BY_1 = 0,
+ UCLK_DIV_BY_2,
+ UCLK_DIV_BY_4,
+ UCLK_DIV_BY_8,
+} UCLK_DIV_e;
+
+typedef enum {
+ GPIO_INT_POLARITY_ACTIVE_LOW = 0,
+ GPIO_INT_POLARITY_ACTIVE_HIGH,
+} GpioIntPolarity_e;
+
+typedef enum {
+ PWR_CONFIG_TDP = 0,
+ PWR_CONFIG_TGP,
+ PWR_CONFIG_TCP_ESTIMATED,
+ PWR_CONFIG_TCP_MEASURED,
+} PwrConfig_e;
+
+typedef struct {
+ uint8_t Padding;
+ uint8_t SnapToDiscrete; // 0 - Fine grained DPM, 1 - Discrete DPM
+ uint8_t NumDiscreteLevels; // Set to 2 (Fmin, Fmax) when using fine grained DPM, otherwise set to # discrete levels used
+ uint8_t CalculateFopt; // Indication whether FW should calculate Fopt or use values below. Reference FOPT_CALC_e
+ LinearInt_t ConversionToAvfsClk; // Transfer function to AVFS Clock (GHz->GHz)
+ uint32_t Padding3[3];
+ uint16_t Padding4;
+ uint16_t FoptimalDc; //Foptimal frequency in DC power mode.
+ uint16_t FoptimalAc; //Foptimal frequency in AC power mode.
+ uint16_t Padding2;
+} DpmDescriptor_t;
+
+typedef enum {
+ PPT_THROTTLER_PPT0,
+ PPT_THROTTLER_PPT1,
+ PPT_THROTTLER_PPT2,
+ PPT_THROTTLER_PPT3,
+ PPT_THROTTLER_COUNT
+} PPT_THROTTLER_e;
+
+typedef enum {
+ TEMP_EDGE,
+ TEMP_HOTSPOT,
+ TEMP_HOTSPOT_G,
+ TEMP_HOTSPOT_M,
+ TEMP_MEM,
+ TEMP_VR_GFX,
+ TEMP_VR_MEM0,
+ TEMP_VR_MEM1,
+ TEMP_VR_SOC,
+ TEMP_VR_U,
+ TEMP_LIQUID0,
+ TEMP_LIQUID1,
+ TEMP_PLX,
+ TEMP_COUNT,
+} TEMP_e;
+
+typedef enum {
+ TDC_THROTTLER_GFX,
+ TDC_THROTTLER_SOC,
+ TDC_THROTTLER_U,
+ TDC_THROTTLER_COUNT
+} TDC_THROTTLER_e;
+
+typedef enum {
+ SVI_PLANE_GFX,
+ SVI_PLANE_SOC,
+ SVI_PLANE_VMEMP,
+ SVI_PLANE_VDDIO_MEM,
+ SVI_PLANE_U,
+ SVI_PLANE_COUNT,
+} SVI_PLANE_e;
+
+typedef enum {
+ PMFW_VOLT_PLANE_GFX,
+ PMFW_VOLT_PLANE_SOC,
+ PMFW_VOLT_PLANE_COUNT
+} PMFW_VOLT_PLANE_e;
+
+typedef enum {
+ CUSTOMER_VARIANT_ROW,
+ CUSTOMER_VARIANT_FALCON,
+ CUSTOMER_VARIANT_COUNT,
+} CUSTOMER_VARIANT_e;
+
+typedef enum {
+ POWER_SOURCE_AC,
+ POWER_SOURCE_DC,
+ POWER_SOURCE_COUNT,
+} POWER_SOURCE_e;
+
+typedef enum {
+ MEM_VENDOR_SAMSUNG,
+ MEM_VENDOR_INFINEON,
+ MEM_VENDOR_ELPIDA,
+ MEM_VENDOR_ETRON,
+ MEM_VENDOR_NANYA,
+ MEM_VENDOR_HYNIX,
+ MEM_VENDOR_MOSEL,
+ MEM_VENDOR_WINBOND,
+ MEM_VENDOR_ESMT,
+ MEM_VENDOR_PLACEHOLDER0,
+ MEM_VENDOR_PLACEHOLDER1,
+ MEM_VENDOR_PLACEHOLDER2,
+ MEM_VENDOR_PLACEHOLDER3,
+ MEM_VENDOR_PLACEHOLDER4,
+ MEM_VENDOR_PLACEHOLDER5,
+ MEM_VENDOR_MICRON,
+ MEM_VENDOR_COUNT,
+} MEM_VENDOR_e;
+
+typedef enum {
+ PP_GRTAVFS_HW_CPO_CTL_ZONE0,
+ PP_GRTAVFS_HW_CPO_CTL_ZONE1,
+ PP_GRTAVFS_HW_CPO_CTL_ZONE2,
+ PP_GRTAVFS_HW_CPO_CTL_ZONE3,
+ PP_GRTAVFS_HW_CPO_CTL_ZONE4,
+ PP_GRTAVFS_HW_CPO_EN_0_31_ZONE0,
+ PP_GRTAVFS_HW_CPO_EN_32_63_ZONE0,
+ PP_GRTAVFS_HW_CPO_EN_0_31_ZONE1,
+ PP_GRTAVFS_HW_CPO_EN_32_63_ZONE1,
+ PP_GRTAVFS_HW_CPO_EN_0_31_ZONE2,
+ PP_GRTAVFS_HW_CPO_EN_32_63_ZONE2,
+ PP_GRTAVFS_HW_CPO_EN_0_31_ZONE3,
+ PP_GRTAVFS_HW_CPO_EN_32_63_ZONE3,
+ PP_GRTAVFS_HW_CPO_EN_0_31_ZONE4,
+ PP_GRTAVFS_HW_CPO_EN_32_63_ZONE4,
+ PP_GRTAVFS_HW_ZONE0_VF,
+ PP_GRTAVFS_HW_ZONE1_VF1,
+ PP_GRTAVFS_HW_ZONE2_VF2,
+ PP_GRTAVFS_HW_ZONE3_VF3,
+ PP_GRTAVFS_HW_VOLTAGE_GB,
+ PP_GRTAVFS_HW_CPOSCALINGCTRL_ZONE0,
+ PP_GRTAVFS_HW_CPOSCALINGCTRL_ZONE1,
+ PP_GRTAVFS_HW_CPOSCALINGCTRL_ZONE2,
+ PP_GRTAVFS_HW_CPOSCALINGCTRL_ZONE3,
+ PP_GRTAVFS_HW_CPOSCALINGCTRL_ZONE4,
+ PP_GRTAVFS_HW_RESERVED_0,
+ PP_GRTAVFS_HW_RESERVED_1,
+ PP_GRTAVFS_HW_RESERVED_2,
+ PP_GRTAVFS_HW_RESERVED_3,
+ PP_GRTAVFS_HW_RESERVED_4,
+ PP_GRTAVFS_HW_RESERVED_5,
+ PP_GRTAVFS_HW_RESERVED_6,
+ PP_GRTAVFS_HW_FUSE_COUNT,
+} PP_GRTAVFS_HW_FUSE_e;
+
+typedef enum {
+ PP_GRTAVFS_FW_COMMON_PPVMIN_Z1_HOT_T0,
+ PP_GRTAVFS_FW_COMMON_PPVMIN_Z1_COLD_T0,
+ PP_GRTAVFS_FW_COMMON_PPVMIN_Z2_HOT_T0,
+ PP_GRTAVFS_FW_COMMON_PPVMIN_Z2_COLD_T0,
+ PP_GRTAVFS_FW_COMMON_PPVMIN_Z3_HOT_T0,
+ PP_GRTAVFS_FW_COMMON_PPVMIN_Z3_COLD_T0,
+ PP_GRTAVFS_FW_COMMON_PPVMIN_Z4_HOT_T0,
+ PP_GRTAVFS_FW_COMMON_PPVMIN_Z4_COLD_T0,
+ PP_GRTAVFS_FW_COMMON_SRAM_RM_Z0,
+ PP_GRTAVFS_FW_COMMON_SRAM_RM_Z1,
+ PP_GRTAVFS_FW_COMMON_SRAM_RM_Z2,
+ PP_GRTAVFS_FW_COMMON_SRAM_RM_Z3,
+ PP_GRTAVFS_FW_COMMON_SRAM_RM_Z4,
+ PP_GRTAVFS_FW_COMMON_FUSE_COUNT,
+} PP_GRTAVFS_FW_COMMON_FUSE_e;
+
+typedef enum {
+ PP_GRTAVFS_FW_SEP_FUSE_GB1_PWL_VOLTAGE_NEG_1,
+ PP_GRTAVFS_FW_SEP_FUSE_GB1_PWL_VOLTAGE_0,
+ PP_GRTAVFS_FW_SEP_FUSE_GB1_PWL_VOLTAGE_1,
+ PP_GRTAVFS_FW_SEP_FUSE_GB1_PWL_VOLTAGE_2,
+ PP_GRTAVFS_FW_SEP_FUSE_GB1_PWL_VOLTAGE_3,
+ PP_GRTAVFS_FW_SEP_FUSE_GB1_PWL_VOLTAGE_4,
+ PP_GRTAVFS_FW_SEP_FUSE_GB2_PWL_VOLTAGE_NEG_1,
+ PP_GRTAVFS_FW_SEP_FUSE_GB2_PWL_VOLTAGE_0,
+ PP_GRTAVFS_FW_SEP_FUSE_GB2_PWL_VOLTAGE_1,
+ PP_GRTAVFS_FW_SEP_FUSE_GB2_PWL_VOLTAGE_2,
+ PP_GRTAVFS_FW_SEP_FUSE_GB2_PWL_VOLTAGE_3,
+ PP_GRTAVFS_FW_SEP_FUSE_GB2_PWL_VOLTAGE_4,
+ PP_GRTAVFS_FW_SEP_FUSE_VF_NEG_1_FREQUENCY,
+ PP_GRTAVFS_FW_SEP_FUSE_VF4_FREQUENCY,
+ PP_GRTAVFS_FW_SEP_FUSE_FREQUENCY_TO_COUNT_SCALER_0,
+ PP_GRTAVFS_FW_SEP_FUSE_FREQUENCY_TO_COUNT_SCALER_1,
+ PP_GRTAVFS_FW_SEP_FUSE_FREQUENCY_TO_COUNT_SCALER_2,
+ PP_GRTAVFS_FW_SEP_FUSE_FREQUENCY_TO_COUNT_SCALER_3,
+ PP_GRTAVFS_FW_SEP_FUSE_FREQUENCY_TO_COUNT_SCALER_4,
+ PP_GRTAVFS_FW_SEP_FUSE_COUNT,
+} PP_GRTAVFS_FW_SEP_FUSE_e;
+
+#define PP_NUM_RTAVFS_PWL_ZONES 5
+
+
+
+// VBIOS or PPLIB configures telemetry slope and offset. Only slope expected to be set for SVI3
+// Slope Q1.7, Offset Q1.2
+typedef struct {
+ int8_t Offset; // in Amps
+ uint8_t Padding;
+ uint16_t MaxCurrent; // in Amps
+} SviTelemetryScale_t;
+
+#define PP_NUM_OD_VF_CURVE_POINTS PP_NUM_RTAVFS_PWL_ZONES + 1
+
+
+typedef struct {
+ uint32_t FeatureCtrlMask;
+
+ //Voltage control
+ int16_t VoltageOffsetPerZoneBoundary[PP_NUM_OD_VF_CURVE_POINTS];
+ uint16_t reserved[2];
+
+ //Frequency changes
+ uint16_t GfxclkFmin; // MHz
+ uint16_t GfxclkFmax; // MHz
+ uint16_t UclkFmin; // MHz
+ uint16_t UclkFmax; // MHz
+
+ //PPT
+ int16_t Ppt; // %
+ int16_t reserved1;
+
+ //Fan control
+ uint8_t FanLinearPwmPoints[NUM_OD_FAN_MAX_POINTS];
+ uint8_t FanLinearTempPoints[NUM_OD_FAN_MAX_POINTS];
+ uint16_t FanMaximumRpm;
+ uint16_t FanMinimumPwm;
+ uint16_t FanAcousticLimitRpm;
+ uint16_t FanTargetTemperature; // Degree Celcius
+ uint8_t FanZeroRpmEnable;
+ uint8_t FanZeroRpmStopTemp;
+ uint8_t FanMode;
+ uint8_t Padding[1];
+
+
+ uint32_t Spare[13];
+ uint32_t MmHubPadding[8]; // SMU internal use. Adding here instead of external as a workaround
+} OverDriveTable_t;
+
+typedef struct {
+ OverDriveTable_t OverDriveTable;
+
+} OverDriveTableExternal_t;
+
+typedef struct {
+ uint32_t FeatureCtrlMask;
+
+ int16_t VoltageOffsetPerZoneBoundary;
+ uint16_t reserved[2];
+
+ uint16_t GfxclkFmin; // MHz
+ uint16_t GfxclkFmax; // MHz
+ uint16_t UclkFmin; // MHz
+ uint16_t UclkFmax; // MHz
+
+ //PPT
+ int16_t Ppt; // %
+ int16_t reserved1;
+
+ uint8_t FanLinearPwmPoints;
+ uint8_t FanLinearTempPoints;
+ uint16_t FanMaximumRpm;
+ uint16_t FanMinimumPwm;
+ uint16_t FanAcousticLimitRpm;
+ uint16_t FanTargetTemperature; // Degree Celcius
+ uint8_t FanZeroRpmEnable;
+ uint8_t FanZeroRpmStopTemp;
+ uint8_t FanMode;
+ uint8_t Padding[1];
+
+
+ uint32_t Spare[13];
+
+} OverDriveLimits_t;
+
+
+typedef enum {
+ BOARD_GPIO_SMUIO_0,
+ BOARD_GPIO_SMUIO_1,
+ BOARD_GPIO_SMUIO_2,
+ BOARD_GPIO_SMUIO_3,
+ BOARD_GPIO_SMUIO_4,
+ BOARD_GPIO_SMUIO_5,
+ BOARD_GPIO_SMUIO_6,
+ BOARD_GPIO_SMUIO_7,
+ BOARD_GPIO_SMUIO_8,
+ BOARD_GPIO_SMUIO_9,
+ BOARD_GPIO_SMUIO_10,
+ BOARD_GPIO_SMUIO_11,
+ BOARD_GPIO_SMUIO_12,
+ BOARD_GPIO_SMUIO_13,
+ BOARD_GPIO_SMUIO_14,
+ BOARD_GPIO_SMUIO_15,
+ BOARD_GPIO_SMUIO_16,
+ BOARD_GPIO_SMUIO_17,
+ BOARD_GPIO_SMUIO_18,
+ BOARD_GPIO_SMUIO_19,
+ BOARD_GPIO_SMUIO_20,
+ BOARD_GPIO_SMUIO_21,
+ BOARD_GPIO_SMUIO_22,
+ BOARD_GPIO_SMUIO_23,
+ BOARD_GPIO_SMUIO_24,
+ BOARD_GPIO_SMUIO_25,
+ BOARD_GPIO_SMUIO_26,
+ BOARD_GPIO_SMUIO_27,
+ BOARD_GPIO_SMUIO_28,
+ BOARD_GPIO_SMUIO_29,
+ BOARD_GPIO_SMUIO_30,
+ BOARD_GPIO_SMUIO_31,
+ MAX_BOARD_GPIO_SMUIO_NUM,
+ BOARD_GPIO_DC_GEN_A,
+ BOARD_GPIO_DC_GEN_B,
+ BOARD_GPIO_DC_GEN_C,
+ BOARD_GPIO_DC_GEN_D,
+ BOARD_GPIO_DC_GEN_E,
+ BOARD_GPIO_DC_GEN_F,
+ BOARD_GPIO_DC_GEN_G,
+ BOARD_GPIO_DC_GENLK_CLK,
+ BOARD_GPIO_DC_GENLK_VSYNC,
+ BOARD_GPIO_DC_SWAPLOCK_A,
+ BOARD_GPIO_DC_SWAPLOCK_B,
+} BOARD_GPIO_TYPE_e;
+
+#define INVALID_BOARD_GPIO 0xFF
+
+
+typedef struct {
+ //PLL 0
+ uint16_t InitGfxclk_bypass;
+ uint16_t InitSocclk;
+ uint16_t InitMp0clk;
+ uint16_t InitMpioclk;
+ uint16_t InitSmnclk;
+ uint16_t InitUcpclk;
+ uint16_t InitCsrclk;
+ //PLL 1
+
+ uint16_t InitDprefclk;
+ uint16_t InitDcfclk;
+ uint16_t InitDtbclk;
+ //PLL 2
+ uint16_t InitDclk; //assume same DCLK/VCLK for both instances
+ uint16_t InitVclk;
+ // PLL 3
+ uint16_t InitUsbdfsclk;
+ uint16_t InitMp1clk;
+ uint16_t InitLclk;
+ uint16_t InitBaco400clk_bypass;
+ uint16_t InitBaco1200clk_bypass;
+ uint16_t InitBaco700clk_bypass;
+ // PLL 4
+ uint16_t InitFclk;
+ // PLL 5
+ uint16_t InitGfxclk_clkb;
+
+ //PLL 6
+ uint8_t InitUclkDPMState; // =0,1,2,3, frequency from FreqTableUclk
+
+ uint8_t Padding[3];
+
+ uint32_t InitVcoFreqPll0;
+ uint32_t InitVcoFreqPll1;
+ uint32_t InitVcoFreqPll2;
+ uint32_t InitVcoFreqPll3;
+ uint32_t InitVcoFreqPll4;
+ uint32_t InitVcoFreqPll5;
+ uint32_t InitVcoFreqPll6;
+
+ //encoding will change depending on SVI2/SVI3
+ uint16_t InitGfx; // In mV(Q2) , should be 0?
+ uint16_t InitSoc; // In mV(Q2)
+ uint16_t InitU; // In Mv(Q2)
+
+ uint16_t Padding2;
+
+ uint32_t Spare[8];
+
+} BootValues_t;
+
+
+typedef struct {
+ uint16_t Power[PPT_THROTTLER_COUNT][POWER_SOURCE_COUNT]; // Watts
+ uint16_t Tdc[TDC_THROTTLER_COUNT]; // Amps
+
+ uint16_t Temperature[TEMP_COUNT]; // Celsius
+
+ uint8_t PwmLimitMin;
+ uint8_t PwmLimitMax;
+ uint8_t FanTargetTemperature;
+ uint8_t Spare1[1];
+
+ uint16_t AcousticTargetRpmThresholdMin;
+ uint16_t AcousticTargetRpmThresholdMax;
+
+ uint16_t AcousticLimitRpmThresholdMin;
+ uint16_t AcousticLimitRpmThresholdMax;
+
+ uint16_t PccLimitMin;
+ uint16_t PccLimitMax;
+
+ uint16_t FanStopTempMin;
+ uint16_t FanStopTempMax;
+ uint16_t FanStartTempMin;
+ uint16_t FanStartTempMax;
+
+ uint32_t Spare[12];
+
+} MsgLimits_t;
+
+typedef struct {
+ uint16_t BaseClockAc;
+ uint16_t GameClockAc;
+ uint16_t BoostClockAc;
+ uint16_t BaseClockDc;
+ uint16_t GameClockDc;
+ uint16_t BoostClockDc;
+
+ uint32_t Reserved[4];
+} DriverReportedClocks_t;
+
+typedef struct {
+ uint8_t DcBtcEnabled;
+ uint8_t Padding[3];
+
+ uint16_t DcTol; // mV Q2
+ uint16_t DcBtcGb; // mV Q2
+
+ uint16_t DcBtcMin; // mV Q2
+ uint16_t DcBtcMax; // mV Q2
+
+ LinearInt_t DcBtcGbScalar;
+
+} AvfsDcBtcParams_t;
+
+typedef struct {
+ uint16_t AvfsTemp[AVFS_TEMP_COUNT]; //in degrees C
+ uint16_t VftFMin; // in MHz
+ uint16_t VInversion; // in mV Q2
+ QuadraticInt_t qVft[AVFS_TEMP_COUNT];
+ QuadraticInt_t qAvfsGb;
+ QuadraticInt_t qAvfsGb2;
+} AvfsFuseOverride_t;
+
+typedef struct {
+ // SECTION: Version
+
+ uint32_t Version; // should be unique to each SKU(i.e if any value changes in below structure then this value must be different)
+
+ // SECTION: Feature Control
+ uint32_t FeaturesToRun[NUM_FEATURES / 32]; // Features that PMFW will attempt to enable. Use FEATURE_*_BIT as mapping
+
+ // SECTION: Miscellaneous Configuration
+ uint8_t TotalPowerConfig; // Determines how PMFW calculates the power. Use defines from PwrConfig_e
+ uint8_t CustomerVariant; //To specify if this PPTable is intended for a particular customer. Use defines from CUSTOMER_VARIANT_e
+ uint8_t MemoryTemperatureTypeMask; // Bit mapping indicating which methods of memory temperature reading are enabled. Use defines from MEM_TEMP_*BIT
+ uint8_t SmartShiftVersion; // Determine what SmartShift feature version is supported Use defines from SMARTSHIFT_VERSION_e
+
+ // SECTION: Infrastructure Limits
+ uint16_t SocketPowerLimitAc[PPT_THROTTLER_COUNT]; // In Watts. Power limit that PMFW attempts to control to in AC mode. Multiple limits supported
+ uint16_t SocketPowerLimitDc[PPT_THROTTLER_COUNT]; // In Watts. Power limit that PMFW attempts to control to in DC mode. Multiple limits supported
+
+ uint16_t SocketPowerLimitSmartShift2; // In Watts. Power limit used SmartShift
+
+ //if set to 1, SocketPowerLimitAc and SocketPowerLimitDc will be interpreted as legacy programs(i.e absolute power). If 0, all except index 0 will be scalars
+ //relative index 0
+ uint8_t EnableLegacyPptLimit;
+ uint8_t UseInputTelemetry; //applicable to SVI3 only and only to be set if VRs support
+ uint8_t SmartShiftMinReportedPptinDcs; //minimum possible active power consumption for this SKU. Used for SmartShift power reporting
+
+ uint8_t PaddingPpt[1];
+
+ uint16_t VrTdcLimit[TDC_THROTTLER_COUNT]; // In Amperes. Current limit associated with VR regulator maximum temperature
+
+ uint16_t PlatformTdcLimit[TDC_THROTTLER_COUNT]; // In Amperes. Current limit associated with platform maximum temperature per VR current rail
+
+ uint16_t TemperatureLimit[TEMP_COUNT]; // In degrees Celsius. Temperature limit associated with each input
+
+ uint16_t HwCtfTempLimit; // In degrees Celsius. Temperature above which HW will trigger CTF. Consumed by VBIOS only
+
+ uint16_t PaddingInfra;
+
+ // Per year normalized Vmax state failure rates (sum of the two domains divided by life time in years)
+ uint32_t FitControllerFailureRateLimit; //in IEEE float
+ //Expected GFX Duty Cycle at Vmax.
+ uint32_t FitControllerGfxDutyCycle; // in IEEE float
+ //Expected SOC Duty Cycle at Vmax.
+ uint32_t FitControllerSocDutyCycle; // in IEEE float
+
+ //This offset will be deducted from the controller output to before it goes through the SOC Vset limiter block.
+ uint32_t FitControllerSocOffset; //in IEEE float
+
+ uint32_t GfxApccPlusResidencyLimit; // Percentage value. Used by APCC+ controller to control PCC residency to some value
+
+ // SECTION: Throttler settings
+ uint32_t ThrottlerControlMask; // See THROTTLER_*_BIT for mapping
+
+ // SECTION: FW DSTATE Settings
+ uint32_t FwDStateMask; // See FW_DSTATE_*_BIT for mapping
+
+ // SECTION: Voltage Control Parameters
+ uint16_t UlvVoltageOffset[PMFW_VOLT_PLANE_COUNT]; // In mV(Q2). ULV offset used in either GFX_ULV or SOC_ULV(part of FW_DSTATE)
+
+ uint16_t UlvVoltageOffsetU; // In mV(Q2). ULV offset used in either U_ULV(part of FW_DSTATE)
+ uint16_t DeepUlvVoltageOffsetSoc; // In mV(Q2) Long Idle Vmin (deep ULV), for VDD_SOC as part of FW_DSTATE
+
+ // Voltage Limits
+ uint16_t DefaultMaxVoltage[PMFW_VOLT_PLANE_COUNT]; // In mV(Q2) Maximum voltage without FIT controller enabled
+ uint16_t BoostMaxVoltage[PMFW_VOLT_PLANE_COUNT]; // In mV(Q2) Maximum voltage with FIT controller enabled
+
+ //Vmin Optimizations
+ int16_t VminTempHystersis[PMFW_VOLT_PLANE_COUNT]; // Celsius Temperature hysteresis for switching between low/high temperature values for Vmin
+ int16_t VminTempThreshold[PMFW_VOLT_PLANE_COUNT]; // Celsius Temperature threshold for switching between low/high temperature values for Vmin
+ uint16_t Vmin_Hot_T0[PMFW_VOLT_PLANE_COUNT]; //In mV(Q2) Initial (pre-aging) Vset to be used at hot.
+ uint16_t Vmin_Cold_T0[PMFW_VOLT_PLANE_COUNT]; //In mV(Q2) Initial (pre-aging) Vset to be used at cold.
+ uint16_t Vmin_Hot_Eol[PMFW_VOLT_PLANE_COUNT]; //In mV(Q2) End-of-life Vset to be used at hot.
+ uint16_t Vmin_Cold_Eol[PMFW_VOLT_PLANE_COUNT]; //In mV(Q2) End-of-life Vset to be used at cold.
+ uint16_t Vmin_Aging_Offset[PMFW_VOLT_PLANE_COUNT]; //In mV(Q2) Worst-case aging margin
+ uint16_t Vmin_Plat_Offset_Hot[PMFW_VOLT_PLANE_COUNT]; //In mV(Q2) Platform offset apply to T0 Hot
+ uint16_t Vmin_Plat_Offset_Cold[PMFW_VOLT_PLANE_COUNT]; //In mV(Q2) Platform offset apply to T0 Cold
+
+ //This is a fixed/minimum VMIN aging degradation offset which is applied at T0. This reflects the minimum amount of aging already accounted for.
+ uint16_t VcBtcFixedVminAgingOffset[PMFW_VOLT_PLANE_COUNT];
+ //Linear offset or GB term to account for mis-correlation between PSM and Vmin shift trends across parts.
+ uint16_t VcBtcVmin2PsmDegrationGb[PMFW_VOLT_PLANE_COUNT];
+ //Scalar coefficient of the PSM aging degradation function
+ uint32_t VcBtcPsmA[PMFW_VOLT_PLANE_COUNT]; // A_PSM
+ //Exponential coefficient of the PSM aging degradation function
+ uint32_t VcBtcPsmB[PMFW_VOLT_PLANE_COUNT]; // B_PSM
+ //Scalar coefficient of the VMIN aging degradation function. Specified as worst case between hot and cold.
+ uint32_t VcBtcVminA[PMFW_VOLT_PLANE_COUNT]; // A_VMIN
+ //Exponential coefficient of the VMIN aging degradation function. Specified as worst case between hot and cold.
+ uint32_t VcBtcVminB[PMFW_VOLT_PLANE_COUNT]; // B_VMIN
+
+ uint8_t PerPartVminEnabled[PMFW_VOLT_PLANE_COUNT];
+ uint8_t VcBtcEnabled[PMFW_VOLT_PLANE_COUNT];
+
+ uint16_t SocketPowerLimitAcTau[PPT_THROTTLER_COUNT]; // Time constant of LPF in ms
+ uint16_t SocketPowerLimitDcTau[PPT_THROTTLER_COUNT]; // Time constant of LPF in ms
+
+ uint32_t SpareVmin[12];
+
+
+ //SECTION: DPM Configuration 1
+ DpmDescriptor_t DpmDescriptor[PPCLK_COUNT];
+
+ uint16_t FreqTableGfx [NUM_GFXCLK_DPM_LEVELS ]; // In MHz
+ uint16_t FreqTableVclk [NUM_VCLK_DPM_LEVELS ]; // In MHz
+ uint16_t FreqTableDclk [NUM_DCLK_DPM_LEVELS ]; // In MHz
+ uint16_t FreqTableSocclk [NUM_SOCCLK_DPM_LEVELS ]; // In MHz
+ uint16_t FreqTableUclk [NUM_UCLK_DPM_LEVELS ]; // In MHz
+ uint16_t FreqTableDispclk [NUM_DISPCLK_DPM_LEVELS ]; // In MHz
+ uint16_t FreqTableDppClk [NUM_DPPCLK_DPM_LEVELS ]; // In MHz
+ uint16_t FreqTableDprefclk [NUM_DPREFCLK_DPM_LEVELS]; // In MHz
+ uint16_t FreqTableDcfclk [NUM_DCFCLK_DPM_LEVELS ]; // In MHz
+ uint16_t FreqTableDtbclk [NUM_DTBCLK_DPM_LEVELS ]; // In MHz
+ uint16_t FreqTableFclk [NUM_FCLK_DPM_LEVELS ]; // In MHz
+
+ uint32_t DcModeMaxFreq [PPCLK_COUNT ]; // In MHz
+
+ // SECTION: DPM Configuration 2
+ uint16_t Mp0clkFreq [NUM_MP0CLK_DPM_LEVELS]; // in MHz
+ uint16_t Mp0DpmVoltage [NUM_MP0CLK_DPM_LEVELS]; // mV(Q2)
+
+ uint8_t GfxclkSpare[2];
+ uint16_t GfxclkFreqCap;
+
+ //GFX Idle Power Settings
+ uint16_t GfxclkFgfxoffEntry; // in Mhz
+ uint16_t GfxclkFgfxoffExitImu; // in Mhz
+ uint16_t GfxclkFgfxoffExitRlc; // in Mhz
+ uint16_t GfxclkThrottleClock; //Used primarily in DCS
+ uint8_t EnableGfxPowerStagesGpio; //Genlk_vsync GPIO flag used to control gfx power stages
+ uint8_t GfxIdlePadding;
+
+ uint8_t SmsRepairWRCKClkDivEn;
+ uint8_t SmsRepairWRCKClkDivVal;
+ uint8_t GfxOffEntryEarlyMGCGEn;
+ uint8_t GfxOffEntryForceCGCGEn;
+ uint8_t GfxOffEntryForceCGCGDelayEn;
+ uint8_t GfxOffEntryForceCGCGDelayVal; // in microseconds
+
+ uint16_t GfxclkFreqGfxUlv; // in MHz
+ uint8_t GfxIdlePadding2[2];
+
+ uint32_t GfxoffSpare[16];
+
+ // GFX GPO
+ uint32_t GfxGpoSpare[16];
+
+ // GFX DCS
+
+ uint16_t DcsGfxOffVoltage; //Voltage in mV(Q2) applied to VDDGFX when entering DCS GFXOFF phase
+ uint16_t PaddingDcs;
+
+ uint16_t DcsMinGfxOffTime; //Minimum amount of time PMFW shuts GFX OFF as part of GFX DCS phase
+ uint16_t DcsMaxGfxOffTime; //Maximum amount of time PMFW can shut GFX OFF as part of GFX DCS phase at a stretch.
+
+ uint32_t DcsMinCreditAccum; //Min amount of positive credit accumulation before waking GFX up as part of DCS.
+
+ uint16_t DcsExitHysteresis; //The min amount of time power credit accumulator should have a value > 0 before SMU exits the DCS throttling phase.
+ uint16_t DcsTimeout; //This is the amount of time SMU FW waits for RLC to put GFX into GFXOFF before reverting to the fallback mechanism of throttling GFXCLK to Fmin.
+
+
+ uint32_t DcsSpare[16];
+
+ // UCLK section
+ uint8_t UseStrobeModeOptimizations; //Set to indicate that FW should use strobe mode optimizations
+ uint8_t PaddingMem[3];
+
+ uint8_t UclkDpmPstates [NUM_UCLK_DPM_LEVELS]; // 4 DPM states, 0-P0, 1-P1, 2-P2, 3-P3.
+ uint8_t FreqTableUclkDiv [NUM_UCLK_DPM_LEVELS ]; // 0:Div-1, 1:Div-1/2, 2:Div-1/4, 3:Div-1/8
+
+ uint16_t MemVmempVoltage [NUM_UCLK_DPM_LEVELS]; // mV(Q2)
+ uint16_t MemVddioVoltage [NUM_UCLK_DPM_LEVELS]; // mV(Q2)
+
+ //FCLK Section
+
+ uint8_t FclkDpmUPstates[NUM_FCLK_DPM_LEVELS]; // U P-state ID associated with each FCLK DPM state.
+ uint16_t FclkDpmVddU[NUM_FCLK_DPM_LEVELS]; // mV(Q2) Vset U voltage associated with each FCLK DPM state.
+ uint16_t FclkDpmUSpeed[NUM_FCLK_DPM_LEVELS]; //U speed associated with each FCLK DPM state
+ uint16_t FclkDpmDisallowPstateFreq; //Frequency which FW will target when indicated that display config cannot support P-state. Set to 0 use FW calculated value
+ uint16_t PaddingFclk;
+
+ // Link DPM Settings
+ uint8_t PcieGenSpeed[NUM_LINK_LEVELS]; ///< 0:PciE-gen1 1:PciE-gen2 2:PciE-gen3 3:PciE-gen4
+ uint8_t PcieLaneCount[NUM_LINK_LEVELS]; ///< 1=x1, 2=x2, 3=x4, 4=x8, 5=x12, 6=x16
+ uint16_t LclkFreq[NUM_LINK_LEVELS];
+
+ // SECTION: Fan Control
+ uint16_t FanStopTemp[TEMP_COUNT]; //Celsius
+ uint16_t FanStartTemp[TEMP_COUNT]; //Celsius
+
+ uint16_t FanGain[TEMP_COUNT];
+ uint16_t FanGainPadding;
+
+ uint16_t FanPwmMin;
+ uint16_t AcousticTargetRpmThreshold;
+ uint16_t AcousticLimitRpmThreshold;
+ uint16_t FanMaximumRpm;
+ uint16_t MGpuAcousticLimitRpmThreshold;
+ uint16_t FanTargetGfxclk;
+ uint32_t TempInputSelectMask;
+ uint8_t FanZeroRpmEnable;
+ uint8_t FanTachEdgePerRev;
+ uint16_t FanTargetTemperature[TEMP_COUNT];
+
+ // The following are AFC override parameters. Leave at 0 to use FW defaults.
+ int16_t FuzzyFan_ErrorSetDelta;
+ int16_t FuzzyFan_ErrorRateSetDelta;
+ int16_t FuzzyFan_PwmSetDelta;
+ uint16_t FuzzyFan_Reserved;
+
+ uint16_t FwCtfLimit[TEMP_COUNT];
+
+ uint16_t IntakeTempEnableRPM;
+ int16_t IntakeTempOffsetTemp;
+ uint16_t IntakeTempReleaseTemp;
+ uint16_t IntakeTempHighIntakeAcousticLimit;
+ uint16_t IntakeTempAcouticLimitReleaseRate;
+
+ uint16_t FanStalledTempLimitOffset;
+ uint16_t FanStalledTriggerRpm;
+ uint16_t FanAbnormalTriggerRpm;
+ uint16_t FanPadding;
+
+ uint32_t FanSpare[14];
+
+ // SECTION: VDD_GFX AVFS
+
+ uint8_t OverrideGfxAvfsFuses;
+ uint8_t GfxAvfsPadding[3];
+
+ uint32_t L2HwRtAvfsFuses[PP_GRTAVFS_HW_FUSE_COUNT]; //see fusedoc for encoding
+ uint32_t SeHwRtAvfsFuses[PP_GRTAVFS_HW_FUSE_COUNT];
+
+ uint32_t CommonRtAvfs[PP_GRTAVFS_FW_COMMON_FUSE_COUNT];
+
+ uint32_t L2FwRtAvfsFuses[PP_GRTAVFS_FW_SEP_FUSE_COUNT];
+ uint32_t SeFwRtAvfsFuses[PP_GRTAVFS_FW_SEP_FUSE_COUNT];
+
+ uint32_t Droop_PWL_F[PP_NUM_RTAVFS_PWL_ZONES];
+ uint32_t Droop_PWL_a[PP_NUM_RTAVFS_PWL_ZONES];
+ uint32_t Droop_PWL_b[PP_NUM_RTAVFS_PWL_ZONES];
+ uint32_t Droop_PWL_c[PP_NUM_RTAVFS_PWL_ZONES];
+
+ uint32_t Static_PWL_Offset[PP_NUM_RTAVFS_PWL_ZONES];
+
+ uint32_t dGbV_dT_vmin;
+ uint32_t dGbV_dT_vmax;
+
+ //Unused: PMFW-9370
+ uint32_t V2F_vmin_range_low;
+ uint32_t V2F_vmin_range_high;
+ uint32_t V2F_vmax_range_low;
+ uint32_t V2F_vmax_range_high;
+
+ AvfsDcBtcParams_t DcBtcGfxParams;
+
+ uint32_t GfxAvfsSpare[32];
+
+ //SECTION: VDD_SOC AVFS
+
+ uint8_t OverrideSocAvfsFuses;
+ uint8_t MinSocAvfsRevision;
+ uint8_t SocAvfsPadding[2];
+
+ AvfsFuseOverride_t SocAvfsFuseOverride[AVFS_D_COUNT];
+
+ DroopInt_t dBtcGbSoc[AVFS_D_COUNT]; // GHz->V BtcGb
+
+ LinearInt_t qAgingGb[AVFS_D_COUNT]; // GHz->V
+
+ QuadraticInt_t qStaticVoltageOffset[AVFS_D_COUNT]; // GHz->V
+
+ AvfsDcBtcParams_t DcBtcSocParams[AVFS_D_COUNT];
+
+ uint32_t SocAvfsSpare[32];
+
+ //SECTION: Boot clock and voltage values
+ BootValues_t BootValues;
+
+ //SECTION: Driver Reported Clocks
+ DriverReportedClocks_t DriverReportedClocks;
+
+ //SECTION: Message Limits
+ MsgLimits_t MsgLimits;
+
+ //SECTION: OverDrive Limits
+ OverDriveLimits_t OverDriveLimitsMin;
+ OverDriveLimits_t OverDriveLimitsBasicMax;
+ uint32_t reserved[22];
+
+ // SECTION: Advanced Options
+ uint32_t DebugOverrides;
+
+ // SECTION: Sku Reserved
+ uint32_t Spare[64];
+
+ // Padding for MMHUB - do not modify this
+ uint32_t MmHubPadding[8];
+
+} SkuTable_t;
+
+typedef struct {
+ // SECTION: Version
+ uint32_t Version; //should be unique to each board type
+
+
+ // SECTION: I2C Control
+ I2cControllerConfig_t I2cControllers[NUM_I2C_CONTROLLERS];
+
+ // SECTION: SVI2 Board Parameters
+ uint8_t VddGfxVrMapping; // Use VR_MAPPING* bitfields
+ uint8_t VddSocVrMapping; // Use VR_MAPPING* bitfields
+ uint8_t VddMem0VrMapping; // Use VR_MAPPING* bitfields
+ uint8_t VddMem1VrMapping; // Use VR_MAPPING* bitfields
+
+ uint8_t GfxUlvPhaseSheddingMask; // set this to 1 to set PSI0/1 to 1 in ULV mode
+ uint8_t SocUlvPhaseSheddingMask; // set this to 1 to set PSI0/1 to 1 in ULV mode
+ uint8_t VmempUlvPhaseSheddingMask; // set this to 1 to set PSI0/1 to 1 in ULV mode
+ uint8_t VddioUlvPhaseSheddingMask; // set this to 1 to set PSI0/1 to 1 in ULV mode
+
+ //SECTION SVI3 Board Parameters
+ uint8_t SlaveAddrMapping[SVI_PLANE_COUNT];
+ uint8_t VrPsiSupport[SVI_PLANE_COUNT];
+
+ uint8_t PaddingPsi[SVI_PLANE_COUNT];
+ uint8_t EnablePsi6[SVI_PLANE_COUNT]; // only applicable in SVI3
+
+ // SECTION: Voltage Regulator Settings
+ SviTelemetryScale_t SviTelemetryScale[SVI_PLANE_COUNT];
+ uint32_t VoltageTelemetryRatio[SVI_PLANE_COUNT]; // This is used for VDDIO Svi2 Div Ratio workaround. It has 16 fractional bits (Q16.16)
+
+ uint8_t DownSlewRateVr[SVI_PLANE_COUNT];
+
+ // SECTION: GPIO Settings
+
+ uint8_t LedOffGpio;
+ uint8_t FanOffGpio;
+ uint8_t GfxVrPowerStageOffGpio;
+
+ uint8_t AcDcGpio; // GPIO pin configured for AC/DC switching
+ uint8_t AcDcPolarity; // GPIO polarity for AC/DC switching
+ uint8_t VR0HotGpio; // GPIO pin configured for VR0 HOT event
+ uint8_t VR0HotPolarity; // GPIO polarity for VR0 HOT event
+
+ uint8_t GthrGpio; // GPIO pin configured for GTHR Event
+ uint8_t GthrPolarity; // replace GPIO polarity for GTHR
+
+ // LED Display Settings
+ uint8_t LedPin0; // GPIO number for LedPin[0]
+ uint8_t LedPin1; // GPIO number for LedPin[1]
+ uint8_t LedPin2; // GPIO number for LedPin[2]
+ uint8_t LedEnableMask;
+
+ uint8_t LedPcie; // GPIO number for PCIE results
+ uint8_t LedError; // GPIO number for Error Cases
+
+ // SECTION: Clock Spread Spectrum
+
+ // UCLK Spread Spectrum
+ uint16_t UclkSpreadPadding;
+ uint16_t UclkSpreadFreq; // kHz
+
+ // UCLK Spread Spectrum
+ uint8_t UclkSpreadPercent[MEM_VENDOR_COUNT];
+
+ // FCLK Spread Spectrum
+ uint8_t FclkSpreadPadding;
+ uint8_t FclkSpreadPercent; // Q4.4
+ uint16_t FclkSpreadFreq; // kHz
+
+ // Section: Memory Config
+ uint8_t DramWidth; // Width of interface to the channel for each DRAM module. See DRAM_BIT_WIDTH_TYPE_e
+ uint8_t PaddingMem1[3];
+
+ // Section: Total Board Power
+ uint16_t TotalBoardPower; //Only needed for TCP Estimated case, where TCP = TGP+Total Board Power
+ uint16_t BoardPowerPadding;
+
+ // SECTION: UMC feature flags
+ uint8_t HsrEnabled;
+ uint8_t VddqOffEnabled;
+ uint8_t PaddingUmcFlags[2];
+
+ uint32_t PostVoltageSetBacoDelay; // in microseconds. Amount of time FW will wait after power good is established or PSI0 command is issued
+ uint32_t BacoEntryDelay; // in milliseconds. Amount of time FW will wait to trigger BACO entry after receiving entry notification from OS
+
+
+ // SECTION: Board Reserved
+ uint32_t BoardSpare[64];
+
+ // SECTION: Structure Padding
+
+ // Padding for MMHUB - do not modify this
+ uint32_t MmHubPadding[8];
+} BoardTable_t;
+
+typedef struct {
+ SkuTable_t SkuTable;
+ BoardTable_t BoardTable;
+} PPTable_t;
+
+typedef struct {
+ // Time constant parameters for clock averages in ms
+ uint16_t GfxclkAverageLpfTau;
+ uint16_t FclkAverageLpfTau;
+ uint16_t UclkAverageLpfTau;
+ uint16_t GfxActivityLpfTau;
+ uint16_t UclkActivityLpfTau;
+ uint16_t SocketPowerLpfTau;
+ uint16_t VcnClkAverageLpfTau;
+ uint16_t VcnUsageAverageLpfTau;
+} DriverSmuConfig_t;
+
+typedef struct {
+ DriverSmuConfig_t DriverSmuConfig;
+
+ uint32_t Spare[8];
+ // Padding - ignore
+ uint32_t MmHubPadding[8]; // SMU internal use
+} DriverSmuConfigExternal_t;
+
+
+typedef struct {
+
+ uint16_t FreqTableGfx [NUM_GFXCLK_DPM_LEVELS ]; // In MHz
+ uint16_t FreqTableVclk [NUM_VCLK_DPM_LEVELS ]; // In MHz
+ uint16_t FreqTableDclk [NUM_DCLK_DPM_LEVELS ]; // In MHz
+ uint16_t FreqTableSocclk [NUM_SOCCLK_DPM_LEVELS ]; // In MHz
+ uint16_t FreqTableUclk [NUM_UCLK_DPM_LEVELS ]; // In MHz
+ uint16_t FreqTableDispclk [NUM_DISPCLK_DPM_LEVELS ]; // In MHz
+ uint16_t FreqTableDppClk [NUM_DPPCLK_DPM_LEVELS ]; // In MHz
+ uint16_t FreqTableDprefclk [NUM_DPREFCLK_DPM_LEVELS]; // In MHz
+ uint16_t FreqTableDcfclk [NUM_DCFCLK_DPM_LEVELS ]; // In MHz
+ uint16_t FreqTableDtbclk [NUM_DTBCLK_DPM_LEVELS ]; // In MHz
+ uint16_t FreqTableFclk [NUM_FCLK_DPM_LEVELS ]; // In MHz
+
+ uint16_t DcModeMaxFreq [PPCLK_COUNT ]; // In MHz
+
+ uint16_t Padding;
+
+ uint32_t Spare[32];
+
+ // Padding - ignore
+ uint32_t MmHubPadding[8]; // SMU internal use
+
+} DriverInfoTable_t;
+
+typedef struct {
+ uint32_t CurrClock[PPCLK_COUNT];
+
+ uint16_t AverageGfxclkFrequencyTarget;
+ uint16_t AverageGfxclkFrequencyPreDs;
+ uint16_t AverageGfxclkFrequencyPostDs;
+ uint16_t AverageFclkFrequencyPreDs;
+ uint16_t AverageFclkFrequencyPostDs;
+ uint16_t AverageMemclkFrequencyPreDs ; // this is scaled to actual memory clock
+ uint16_t AverageMemclkFrequencyPostDs ; // this is scaled to actual memory clock
+ uint16_t AverageVclk0Frequency ;
+ uint16_t AverageDclk0Frequency ;
+ uint16_t AverageVclk1Frequency ;
+ uint16_t AverageDclk1Frequency ;
+
+ uint16_t AvgVoltage[SVI_PLANE_COUNT];
+
+ uint16_t AverageGfxActivity ;
+ uint16_t AverageUclkActivity ;
+ uint16_t Vcn0ActivityPercentage ;
+ uint16_t Vcn1ActivityPercentage ;
+
+ uint32_t EnergyAccumulator;
+ uint16_t AverageSocketPower ;
+ uint16_t AvgTemperature[TEMP_COUNT];
+
+ uint8_t PcieRate ;
+ uint8_t PcieWidth ;
+
+ uint8_t AvgFanPwm;
+ uint8_t Padding[1];
+ uint16_t AvgFanRpm;
+
+
+ uint8_t ThrottlingPercentage[THROTTLER_COUNT];
+
+ //metrics for D3hot entry/exit and driver ARM msgs
+ uint32_t D3HotEntryCountPerMode[D3HOT_SEQUENCE_COUNT];
+ uint32_t D3HotExitCountPerMode[D3HOT_SEQUENCE_COUNT];
+ uint32_t ArmMsgReceivedCountPerMode[D3HOT_SEQUENCE_COUNT];
+
+ uint16_t ApuSTAPMSmartShiftLimit;
+ uint16_t ApuSTAPMLimit;
+ uint16_t AvgApuSocketPower;
+
+ uint16_t AverageUclkActivity_MAX;
+
+ uint32_t PublicSerialNumberLower;
+ uint32_t PublicSerialNumberUpper;
+
+} SmuMetrics_t;
+
+typedef struct {
+ SmuMetrics_t SmuMetrics;
+ uint32_t Spare[30];
+
+ // Padding - ignore
+ uint32_t MmHubPadding[8]; // SMU internal use
+} SmuMetricsExternal_t;
+
+typedef struct {
+ uint8_t WmSetting;
+ uint8_t Flags;
+ uint8_t Padding[2];
+
+} WatermarkRowGeneric_t;
+
+#define NUM_WM_RANGES 4
+
+typedef enum {
+ WATERMARKS_CLOCK_RANGE = 0,
+ WATERMARKS_DUMMY_PSTATE,
+ WATERMARKS_MALL,
+ WATERMARKS_COUNT,
+} WATERMARKS_FLAGS_e;
+
+typedef struct {
+ // Watermarks
+ WatermarkRowGeneric_t WatermarkRow[NUM_WM_RANGES];
+} Watermarks_t;
+
+typedef struct {
+ Watermarks_t Watermarks;
+ uint32_t Spare[16];
+
+ uint32_t MmHubPadding[8]; // SMU internal use
+} WatermarksExternal_t;
+
+typedef struct {
+ uint16_t avgPsmCount[214];
+ uint16_t minPsmCount[214];
+ float avgPsmVoltage[214];
+ float minPsmVoltage[214];
+} AvfsDebugTable_t;
+
+typedef struct {
+ AvfsDebugTable_t AvfsDebugTable;
+
+ uint32_t MmHubPadding[8]; // SMU internal use
+} AvfsDebugTableExternal_t;
+
+
+typedef struct {
+ uint8_t Gfx_ActiveHystLimit;
+ uint8_t Gfx_IdleHystLimit;
+ uint8_t Gfx_FPS;
+ uint8_t Gfx_MinActiveFreqType;
+ uint8_t Gfx_BoosterFreqType;
+ uint8_t PaddingGfx;
+ uint16_t Gfx_MinActiveFreq; // MHz
+ uint16_t Gfx_BoosterFreq; // MHz
+ uint16_t Gfx_PD_Data_time_constant; // Time constant of PD controller in ms
+ uint32_t Gfx_PD_Data_limit_a; // Q16
+ uint32_t Gfx_PD_Data_limit_b; // Q16
+ uint32_t Gfx_PD_Data_limit_c; // Q16
+ uint32_t Gfx_PD_Data_error_coeff; // Q16
+ uint32_t Gfx_PD_Data_error_rate_coeff; // Q16
+
+ uint8_t Fclk_ActiveHystLimit;
+ uint8_t Fclk_IdleHystLimit;
+ uint8_t Fclk_FPS;
+ uint8_t Fclk_MinActiveFreqType;
+ uint8_t Fclk_BoosterFreqType;
+ uint8_t PaddingFclk;
+ uint16_t Fclk_MinActiveFreq; // MHz
+ uint16_t Fclk_BoosterFreq; // MHz
+ uint16_t Fclk_PD_Data_time_constant; // Time constant of PD controller in ms
+ uint32_t Fclk_PD_Data_limit_a; // Q16
+ uint32_t Fclk_PD_Data_limit_b; // Q16
+ uint32_t Fclk_PD_Data_limit_c; // Q16
+ uint32_t Fclk_PD_Data_error_coeff; // Q16
+ uint32_t Fclk_PD_Data_error_rate_coeff; // Q16
+
+ uint32_t Mem_UpThreshold_Limit[NUM_UCLK_DPM_LEVELS]; // Q16
+ uint8_t Mem_UpHystLimit[NUM_UCLK_DPM_LEVELS];
+ uint8_t Mem_DownHystLimit[NUM_UCLK_DPM_LEVELS];
+ uint16_t Mem_Fps;
+ uint8_t padding[2];
+
+} DpmActivityMonitorCoeffInt_t;
+
+
+typedef struct {
+ DpmActivityMonitorCoeffInt_t DpmActivityMonitorCoeffInt;
+ uint32_t MmHubPadding[8]; // SMU internal use
+} DpmActivityMonitorCoeffIntExternal_t;
+
+
+
+// Workload bits
+#define WORKLOAD_PPLIB_DEFAULT_BIT 0
+#define WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT 1
+#define WORKLOAD_PPLIB_POWER_SAVING_BIT 2
+#define WORKLOAD_PPLIB_VIDEO_BIT 3
+#define WORKLOAD_PPLIB_VR_BIT 4
+#define WORKLOAD_PPLIB_COMPUTE_BIT 5
+#define WORKLOAD_PPLIB_CUSTOM_BIT 6
+#define WORKLOAD_PPLIB_WINDOW_3D_BIT 7
+#define WORKLOAD_PPLIB_COUNT 8
+
+
+// These defines are used with the following messages:
+// SMC_MSG_TransferTableDram2Smu
+// SMC_MSG_TransferTableSmu2Dram
+
+// Table transfer status
+#define TABLE_TRANSFER_OK 0x0
+#define TABLE_TRANSFER_FAILED 0xFF
+#define TABLE_TRANSFER_PENDING 0xAB
+
+// Table types
+#define TABLE_PPTABLE 0
+#define TABLE_COMBO_PPTABLE 1
+#define TABLE_WATERMARKS 2
+#define TABLE_AVFS_PSM_DEBUG 3
+#define TABLE_PMSTATUSLOG 4
+#define TABLE_SMU_METRICS 5
+#define TABLE_DRIVER_SMU_CONFIG 6
+#define TABLE_ACTIVITY_MONITOR_COEFF 7
+#define TABLE_OVERDRIVE 8
+#define TABLE_I2C_COMMANDS 9
+#define TABLE_DRIVER_INFO 10
+#define TABLE_ECCINFO 11
+#define TABLE_COUNT 12
+
+//IH Interupt ID
+#define IH_INTERRUPT_ID_TO_DRIVER 0xFE
+#define IH_INTERRUPT_CONTEXT_ID_BACO 0x2
+#define IH_INTERRUPT_CONTEXT_ID_AC 0x3
+#define IH_INTERRUPT_CONTEXT_ID_DC 0x4
+#define IH_INTERRUPT_CONTEXT_ID_AUDIO_D0 0x5
+#define IH_INTERRUPT_CONTEXT_ID_AUDIO_D3 0x6
+#define IH_INTERRUPT_CONTEXT_ID_THERMAL_THROTTLING 0x7
+
+#endif
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_4.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_4.h
new file mode 100644
index 000000000000..76f695a1d065
--- /dev/null
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_4.h
@@ -0,0 +1,267 @@
+/*
+ * Copyright 2022 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __SMU13_DRIVER_IF_V13_0_4_H__
+#define __SMU13_DRIVER_IF_V13_0_4_H__
+
+// *** IMPORTANT ***
+// SMU TEAM: Always increment the interface version if
+// any structure is changed in this file
+#define PMFW_DRIVER_IF_VERSION 4
+
+typedef struct {
+ int32_t value;
+ uint32_t numFractionalBits;
+} FloatInIntFormat_t;
+
+typedef enum {
+ DSPCLK_DCFCLK = 0,
+ DSPCLK_DISPCLK,
+ DSPCLK_PIXCLK,
+ DSPCLK_PHYCLK,
+ DSPCLK_COUNT,
+} DSPCLK_e;
+
+typedef struct {
+ uint16_t Freq; // in MHz
+ uint16_t Vid; // min voltage in SVI3 VID
+} DisplayClockTable_t;
+
+typedef struct {
+ uint16_t MinClock; // This is either DCFCLK or SOCCLK (in MHz)
+ uint16_t MaxClock; // This is either DCFCLK or SOCCLK (in MHz)
+ uint16_t MinMclk;
+ uint16_t MaxMclk;
+
+ uint8_t WmSetting;
+ uint8_t WmType; // Used for normal pstate change or memory retraining
+ uint8_t Padding[2];
+} WatermarkRowGeneric_t;
+
+#define NUM_WM_RANGES 4
+#define WM_PSTATE_CHG 0
+#define WM_RETRAINING 1
+
+typedef enum {
+ WM_SOCCLK = 0,
+ WM_DCFCLK,
+ WM_COUNT,
+} WM_CLOCK_e;
+
+typedef struct {
+ // Watermarks
+ WatermarkRowGeneric_t WatermarkRow[WM_COUNT][NUM_WM_RANGES];
+
+ uint32_t MmHubPadding[7]; // SMU internal use
+} Watermarks_t;
+
+typedef enum {
+ CUSTOM_DPM_SETTING_GFXCLK,
+ CUSTOM_DPM_SETTING_CCLK,
+ CUSTOM_DPM_SETTING_FCLK_CCX,
+ CUSTOM_DPM_SETTING_FCLK_GFX,
+ CUSTOM_DPM_SETTING_FCLK_STALLS,
+ CUSTOM_DPM_SETTING_LCLK,
+ CUSTOM_DPM_SETTING_COUNT,
+} CUSTOM_DPM_SETTING_e;
+
+typedef struct {
+ uint8_t ActiveHystLimit;
+ uint8_t IdleHystLimit;
+ uint8_t FPS;
+ uint8_t MinActiveFreqType;
+ FloatInIntFormat_t MinActiveFreq;
+ FloatInIntFormat_t PD_Data_limit;
+ FloatInIntFormat_t PD_Data_time_constant;
+ FloatInIntFormat_t PD_Data_error_coeff;
+ FloatInIntFormat_t PD_Data_error_rate_coeff;
+} DpmActivityMonitorCoeffExt_t;
+
+typedef struct {
+ DpmActivityMonitorCoeffExt_t DpmActivityMonitorCoeff[CUSTOM_DPM_SETTING_COUNT];
+} CustomDpmSettings_t;
+
+#define NUM_DCFCLK_DPM_LEVELS 8
+#define NUM_DISPCLK_DPM_LEVELS 8
+#define NUM_DPPCLK_DPM_LEVELS 8
+#define NUM_SOCCLK_DPM_LEVELS 8
+#define NUM_VCN_DPM_LEVELS 8
+#define NUM_SOC_VOLTAGE_LEVELS 8
+#define NUM_DF_PSTATE_LEVELS 4
+
+typedef struct {
+ uint32_t FClk;
+ uint32_t MemClk;
+ uint32_t Voltage;
+ uint8_t WckRatio;
+ uint8_t Spare[3];
+} DfPstateTable_t;
+
+//Freq in MHz
+//Voltage in milli volts with 2 fractional bits
+typedef struct {
+ uint32_t DcfClocks[NUM_DCFCLK_DPM_LEVELS];
+ uint32_t DispClocks[NUM_DISPCLK_DPM_LEVELS];
+ uint32_t DppClocks[NUM_DPPCLK_DPM_LEVELS];
+ uint32_t SocClocks[NUM_SOCCLK_DPM_LEVELS];
+ uint32_t VClocks[NUM_VCN_DPM_LEVELS];
+ uint32_t DClocks[NUM_VCN_DPM_LEVELS];
+ uint32_t SocVoltage[NUM_SOC_VOLTAGE_LEVELS];
+ DfPstateTable_t DfPstateTable[NUM_DF_PSTATE_LEVELS];
+
+ uint8_t NumDcfClkLevelsEnabled;
+ uint8_t NumDispClkLevelsEnabled; //Applies to both Dispclk and Dppclk
+ uint8_t NumSocClkLevelsEnabled;
+ uint8_t VcnClkLevelsEnabled; //Applies to both Vclk and Dclk
+ uint8_t NumDfPstatesEnabled;
+ uint8_t spare[3];
+
+ uint32_t MinGfxClk;
+ uint32_t MaxGfxClk;
+} DpmClocks_t;
+
+
+// Throttler Status Bitmask
+#define THROTTLER_STATUS_BIT_SPL 0
+#define THROTTLER_STATUS_BIT_FPPT 1
+#define THROTTLER_STATUS_BIT_SPPT 2
+#define THROTTLER_STATUS_BIT_SPPT_APU 3
+#define THROTTLER_STATUS_BIT_THM_CORE 4
+#define THROTTLER_STATUS_BIT_THM_GFX 5
+#define THROTTLER_STATUS_BIT_THM_SOC 6
+#define THROTTLER_STATUS_BIT_TDC_VDD 7
+#define THROTTLER_STATUS_BIT_TDC_SOC 8
+#define THROTTLER_STATUS_BIT_PROCHOT_CPU 9
+#define THROTTLER_STATUS_BIT_PROCHOT_GFX 10
+#define THROTTLER_STATUS_BIT_EDC_CPU 11
+#define THROTTLER_STATUS_BIT_EDC_GFX 12
+
+typedef struct {
+ uint16_t GfxclkFrequency; //[MHz]
+ uint16_t SocclkFrequency; //[MHz]
+ uint16_t VclkFrequency; //[MHz]
+ uint16_t DclkFrequency; //[MHz]
+ uint16_t MemclkFrequency; //[MHz]
+ uint16_t spare; //[centi]
+ uint16_t UvdActivity; //[centi]
+ uint16_t GfxActivity; //[centi]
+
+ uint16_t Voltage[2]; //[mV] indices: VDDCR_VDD, VDDCR_SOC
+ uint16_t Current[2]; //[mA] indices: VDDCR_VDD, VDDCR_SOC
+ uint16_t Power[2]; //[mW] indices: VDDCR_VDD, VDDCR_SOC
+
+ //3rd party tools in Windows need this info in the case of APUs
+ uint16_t CoreFrequency[8]; //[MHz]
+ uint16_t CorePower[8]; //[mW]
+ uint16_t CoreTemperature[8]; //[centi-Celsius]
+ uint16_t L3Frequency; //[MHz]
+ uint16_t L3Temperature; //[centi-Celsius]
+
+ uint16_t GfxTemperature; //[centi-Celsius]
+ uint16_t SocTemperature; //[centi-Celsius]
+ uint16_t ThrottlerStatus;
+
+ uint16_t CurrentSocketPower; //[mW]
+ uint16_t StapmOpnLimit; //[W]
+ uint16_t StapmCurrentLimit; //[W]
+ uint32_t ApuPower; //[mW]
+ uint32_t dGpuPower; //[mW]
+
+ uint16_t VddTdcValue; //[mA]
+ uint16_t SocTdcValue; //[mA]
+ uint16_t VddEdcValue; //[mA]
+ uint16_t SocEdcValue; //[mA]
+
+ uint16_t InfrastructureCpuMaxFreq; //[MHz]
+ uint16_t InfrastructureGfxMaxFreq; //[MHz]
+
+ uint16_t SkinTemp;
+ uint16_t DeviceState;
+} SmuMetrics_t;
+
+typedef struct {
+ uint16_t StapmMaxPlatformLimit; //[W]
+ uint16_t StapmMinPlatformLimit; //[W]
+ uint16_t FastPptMaxPlatformLimit; //[W]
+ uint16_t FastPptMinPlatformLimit; //[W]
+ uint16_t SlowPptMaxPlatformLimit; //[W]
+ uint16_t SlowPptMinPlatformLimit; //[W]
+ uint16_t SlowPptApuMaxPlatformLimit; //[W]
+ uint16_t SlowPptApuMinPlatformLimit; //[W]
+} PmfInfo_t;
+
+//ISP tile definitions
+typedef enum {
+ TILE_ISPX = 0, // ISPX
+ TILE_ISPM, // ISPM
+ TILE_ISPC, // ISPCORE
+ TILE_ISPPRE, // ISPPRE
+ TILE_ISPPOST0, // ISPPOST0,
+ TILE_ISPPOST1, // ISPPOST1
+ TILE_MAX
+} TILE_NUM_e;
+
+// Tile Selection (Based on arguments)
+#define TILE_SEL_ISPX (1<<(TILE_ISPX))
+#define TILE_SEL_ISPM (1<<(TILE_ISPM))
+#define TILE_SEL_ISPC (1<<(TILE_ISPC))
+#define TILE_SEL_ISPPRE (1<<(TILE_ISPPRE))
+#define TILE_SEL_ISPPOST0 (1<<(TILE_ISPPOST0))
+#define TILE_SEL_ISPPOST1 (1<<(TILE_ISPPOST1))
+
+
+// Mask for ISP tiles in PGFSM PWR Status Registers
+//Bit[1:0] maps to ISPX, (ISPX)
+//Bit[3:2] maps to ISPM, (ISPM)
+//Bit[5:4] maps to ISPCORE, (ISPCORE)
+//Bit[7:6] maps to ISPPRE, (ISPPRE)
+//Bit[9:8] maps to POST, (ISPPOST
+#define TILE_ISPX_MASK ((1<<0) | (1<<1))
+#define TILE_ISPM_MASK ((1<<2) | (1<<3))
+#define TILE_ISPC_MASK ((1<<4) | (1<<5))
+#define TILE_ISPPRE_MASK ((1<<6) | (1<<7))
+#define TILE_ISPPOST0_MASK ((1<<8) | (1<<9))
+#define TILE_ISPPOST1_MASK ((1<<10) | (1<<11))
+
+
+// Workload bits
+#define WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT 0
+#define WORKLOAD_PPLIB_VIDEO_BIT 2
+#define WORKLOAD_PPLIB_VR_BIT 3
+#define WORKLOAD_PPLIB_COMPUTE_BIT 4
+#define WORKLOAD_PPLIB_CUSTOM_BIT 5
+#define WORKLOAD_PPLIB_COUNT 6
+
+#define TABLE_BIOS_IF 0 // Called by BIOS
+#define TABLE_WATERMARKS 1 // Called by DAL through VBIOS
+#define TABLE_CUSTOM_DPM 2 // Called by Driver
+#define TABLE_SPARE1 3
+#define TABLE_DPMCLOCKS 4 // Called by Driver and VBIOS
+#define TABLE_MOMENTARY_PM 5 // Called by Tools
+#define TABLE_MODERN_STDBY 6 // Called by Tools for Modern Standby Log
+#define TABLE_SMU_METRICS 7 // Called by Driver and PMF
+#define TABLE_INFRASTRUCTURE_LIMITS 8 // Called by PMF
+#define TABLE_COUNT 9
+
+#endif
+
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_7.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_7.h
new file mode 100644
index 000000000000..d99b4b47d49d
--- /dev/null
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_7.h
@@ -0,0 +1,1562 @@
+/*
+ * Copyright 2022 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+#ifndef SMU13_DRIVER_IF_SMU_13_0_7_H
+#define SMU13_DRIVER_IF_SMU_13_0_7_H
+
+// *** IMPORTANT ***
+// PMFW TEAM: Always increment the interface version on any change to this file
+#define SMU13_DRIVER_IF_VERSION 0x28
+
+//Increment this version if SkuTable_t or BoardTable_t change
+#define PPTABLE_VERSION 0x1D
+
+#define NUM_GFXCLK_DPM_LEVELS 16
+#define NUM_SOCCLK_DPM_LEVELS 8
+#define NUM_MP0CLK_DPM_LEVELS 2
+#define NUM_DCLK_DPM_LEVELS 8
+#define NUM_VCLK_DPM_LEVELS 8
+#define NUM_DISPCLK_DPM_LEVELS 8
+#define NUM_DPPCLK_DPM_LEVELS 8
+#define NUM_DPREFCLK_DPM_LEVELS 8
+#define NUM_DCFCLK_DPM_LEVELS 8
+#define NUM_DTBCLK_DPM_LEVELS 8
+#define NUM_UCLK_DPM_LEVELS 4
+#define NUM_LINK_LEVELS 3
+#define NUM_FCLK_DPM_LEVELS 8
+#define NUM_OD_FAN_MAX_POINTS 6
+
+// Feature Control Defines
+#define FEATURE_FW_DATA_READ_BIT 0
+#define FEATURE_DPM_GFXCLK_BIT 1
+#define FEATURE_DPM_GFX_POWER_OPTIMIZER_BIT 2
+#define FEATURE_DPM_UCLK_BIT 3
+#define FEATURE_DPM_FCLK_BIT 4
+#define FEATURE_DPM_SOCCLK_BIT 5
+#define FEATURE_DPM_MP0CLK_BIT 6
+#define FEATURE_DPM_LINK_BIT 7
+#define FEATURE_DPM_DCN_BIT 8
+#define FEATURE_VMEMP_SCALING_BIT 9
+#define FEATURE_VDDIO_MEM_SCALING_BIT 10
+#define FEATURE_DS_GFXCLK_BIT 11
+#define FEATURE_DS_SOCCLK_BIT 12
+#define FEATURE_DS_FCLK_BIT 13
+#define FEATURE_DS_LCLK_BIT 14
+#define FEATURE_DS_DCFCLK_BIT 15
+#define FEATURE_DS_UCLK_BIT 16
+#define FEATURE_GFX_ULV_BIT 17
+#define FEATURE_FW_DSTATE_BIT 18
+#define FEATURE_GFXOFF_BIT 19
+#define FEATURE_BACO_BIT 20
+#define FEATURE_MM_DPM_BIT 21
+#define FEATURE_SOC_MPCLK_DS_BIT 22
+#define FEATURE_BACO_MPCLK_DS_BIT 23
+#define FEATURE_THROTTLERS_BIT 24
+#define FEATURE_SMARTSHIFT_BIT 25
+#define FEATURE_GTHR_BIT 26
+#define FEATURE_ACDC_BIT 27
+#define FEATURE_VR0HOT_BIT 28
+#define FEATURE_FW_CTF_BIT 29
+#define FEATURE_FAN_CONTROL_BIT 30
+#define FEATURE_GFX_DCS_BIT 31
+#define FEATURE_GFX_READ_MARGIN_BIT 32
+#define FEATURE_LED_DISPLAY_BIT 33
+#define FEATURE_GFXCLK_SPREAD_SPECTRUM_BIT 34
+#define FEATURE_OUT_OF_BAND_MONITOR_BIT 35
+#define FEATURE_OPTIMIZED_VMIN_BIT 36
+#define FEATURE_GFX_IMU_BIT 37
+#define FEATURE_BOOT_TIME_CAL_BIT 38
+#define FEATURE_GFX_PCC_DFLL_BIT 39
+#define FEATURE_SOC_CG_BIT 40
+#define FEATURE_DF_CSTATE_BIT 41
+#define FEATURE_GFX_EDC_BIT 42
+#define FEATURE_BOOT_POWER_OPT_BIT 43
+#define FEATURE_CLOCK_POWER_DOWN_BYPASS_BIT 44
+#define FEATURE_DS_VCN_BIT 45
+#define FEATURE_BACO_CG_BIT 46
+#define FEATURE_MEM_TEMP_READ_BIT 47
+#define FEATURE_ATHUB_MMHUB_PG_BIT 48
+#define FEATURE_SOC_PCC_BIT 49
+#define FEATURE_SPARE_50_BIT 50
+#define FEATURE_SPARE_51_BIT 51
+#define FEATURE_SPARE_52_BIT 52
+#define FEATURE_SPARE_53_BIT 53
+#define FEATURE_SPARE_54_BIT 54
+#define FEATURE_SPARE_55_BIT 55
+#define FEATURE_SPARE_56_BIT 56
+#define FEATURE_SPARE_57_BIT 57
+#define FEATURE_SPARE_58_BIT 58
+#define FEATURE_SPARE_59_BIT 59
+#define FEATURE_SPARE_60_BIT 60
+#define FEATURE_SPARE_61_BIT 61
+#define FEATURE_SPARE_62_BIT 62
+#define FEATURE_SPARE_63_BIT 63
+#define NUM_FEATURES 64
+
+//For use with feature control messages
+typedef enum {
+ FEATURE_PWR_ALL,
+ FEATURE_PWR_S5,
+ FEATURE_PWR_BACO,
+ FEATURE_PWR_SOC,
+ FEATURE_PWR_GFX,
+ FEATURE_PWR_DOMAIN_COUNT,
+} FEATURE_PWR_DOMAIN_e;
+
+
+// Debug Overrides Bitmask
+#define DEBUG_OVERRIDE_DISABLE_VOLT_LINK_VCN_FCLK 0x00000001
+#define DEBUG_OVERRIDE_DISABLE_VOLT_LINK_DCN_FCLK 0x00000002
+#define DEBUG_OVERRIDE_DISABLE_VOLT_LINK_MP0_FCLK 0x00000004
+#define DEBUG_OVERRIDE_DISABLE_VOLT_LINK_VCN_DCFCLK 0x00000008
+#define DEBUG_OVERRIDE_DISABLE_FAST_FCLK_TIMER 0x00000010
+#define DEBUG_OVERRIDE_DISABLE_VCN_PG 0x00000020
+#define DEBUG_OVERRIDE_DISABLE_FMAX_VMAX 0x00000040
+#define DEBUG_OVERRIDE_DISABLE_IMU_FW_CHECKS 0x00000080
+#define DEBUG_OVERRIDE_DISABLE_D0i2_REENTRY_HSR_TIMER_CHECK 0x00000100
+#define DEBUG_OVERRIDE_DISABLE_DFLL 0x00000200
+#define DEBUG_OVERRIDE_ENABLE_RLC_VF_BRINGUP_MODE 0x00000400
+#define DEBUG_OVERRIDE_DFLL_MASTER_MODE 0x00000800
+
+// VR Mapping Bit Defines
+#define VR_MAPPING_VR_SELECT_MASK 0x01
+#define VR_MAPPING_VR_SELECT_SHIFT 0x00
+
+#define VR_MAPPING_PLANE_SELECT_MASK 0x02
+#define VR_MAPPING_PLANE_SELECT_SHIFT 0x01
+
+// PSI Bit Defines
+#define PSI_SEL_VR0_PLANE0_PSI0 0x01
+#define PSI_SEL_VR0_PLANE0_PSI1 0x02
+#define PSI_SEL_VR0_PLANE1_PSI0 0x04
+#define PSI_SEL_VR0_PLANE1_PSI1 0x08
+#define PSI_SEL_VR1_PLANE0_PSI0 0x10
+#define PSI_SEL_VR1_PLANE0_PSI1 0x20
+#define PSI_SEL_VR1_PLANE1_PSI0 0x40
+#define PSI_SEL_VR1_PLANE1_PSI1 0x80
+
+typedef enum {
+ SVI_PSI_0, // Full phase count (default)
+ SVI_PSI_1, // Phase count 1st level
+ SVI_PSI_2, // Phase count 2nd level
+ SVI_PSI_3, // Single phase operation + active diode emulation
+ SVI_PSI_4, // Single phase operation + passive diode emulation *optional*
+ SVI_PSI_5, // Reserved
+ SVI_PSI_6, // Power down to 0V (voltage regulation disabled)
+ SVI_PSI_7, // Automated phase shedding and diode emulation
+} SVI_PSI_e;
+
+// Throttler Control/Status Bits
+#define THROTTLER_TEMP_EDGE_BIT 0
+#define THROTTLER_TEMP_HOTSPOT_BIT 1
+#define THROTTLER_TEMP_HOTSPOT_G_BIT 2
+#define THROTTLER_TEMP_HOTSPOT_M_BIT 3
+#define THROTTLER_TEMP_MEM_BIT 4
+#define THROTTLER_TEMP_VR_GFX_BIT 5
+#define THROTTLER_TEMP_VR_MEM0_BIT 6
+#define THROTTLER_TEMP_VR_MEM1_BIT 7
+#define THROTTLER_TEMP_VR_SOC_BIT 8
+#define THROTTLER_TEMP_VR_U_BIT 9
+#define THROTTLER_TEMP_LIQUID0_BIT 10
+#define THROTTLER_TEMP_LIQUID1_BIT 11
+#define THROTTLER_TEMP_PLX_BIT 12
+#define THROTTLER_TDC_GFX_BIT 13
+#define THROTTLER_TDC_SOC_BIT 14
+#define THROTTLER_TDC_U_BIT 15
+#define THROTTLER_PPT0_BIT 16
+#define THROTTLER_PPT1_BIT 17
+#define THROTTLER_PPT2_BIT 18
+#define THROTTLER_PPT3_BIT 19
+#define THROTTLER_FIT_BIT 20
+#define THROTTLER_GFX_APCC_PLUS_BIT 21
+#define THROTTLER_COUNT 22
+
+// FW DState Features Control Bits
+#define FW_DSTATE_SOC_ULV_BIT 0
+#define FW_DSTATE_G6_HSR_BIT 1
+#define FW_DSTATE_G6_PHY_VMEMP_OFF_BIT 2
+#define FW_DSTATE_SMN_DS_BIT 3
+#define FW_DSTATE_MP1_WHISPER_MODE_BIT 4
+#define FW_DSTATE_SOC_LIV_MIN_BIT 5
+#define FW_DSTATE_SOC_PLL_PWRDN_BIT 6
+#define FW_DSTATE_MEM_PLL_PWRDN_BIT 7
+#define FW_DSTATE_MALL_ALLOC_BIT 8
+#define FW_DSTATE_MEM_PSI_BIT 9
+#define FW_DSTATE_HSR_NON_STROBE_BIT 10
+#define FW_DSTATE_MP0_ENTER_WFI_BIT 11
+#define FW_DSTATE_U_ULV_BIT 12
+#define FW_DSTATE_MALL_FLUSH_BIT 13
+#define FW_DSTATE_SOC_PSI_BIT 14
+#define FW_DSTATE_U_PSI_BIT 15
+#define FW_DSTATE_UCP_DS_BIT 16
+#define FW_DSTATE_CSRCLK_DS_BIT 17
+#define FW_DSTATE_MMHUB_INTERLOCK_BIT 18
+#define FW_DSTATE_D0i3_2_QUIET_FW_BIT 19
+#define FW_DSTATE_CLDO_PRG_BIT 20
+#define FW_DSTATE_DF_PLL_PWRDN_BIT 21
+#define FW_DSTATE_U_LOW_PWR_MODE_EN_BIT 22
+#define FW_DSTATE_GFX_PSI6_BIT 23
+#define FW_DSTATE_GFX_VR_PWR_STAGE_BIT 24
+
+//LED Display Mask & Control Bits
+#define LED_DISPLAY_GFX_DPM_BIT 0
+#define LED_DISPLAY_PCIE_BIT 1
+#define LED_DISPLAY_ERROR_BIT 2
+
+
+#define MEM_TEMP_READ_OUT_OF_BAND_BIT 0
+#define MEM_TEMP_READ_IN_BAND_REFRESH_BIT 1
+#define MEM_TEMP_READ_IN_BAND_DUMMY_PSTATE_BIT 2
+
+typedef enum {
+ SMARTSHIFT_VERSION_1,
+ SMARTSHIFT_VERSION_2,
+ SMARTSHIFT_VERSION_3,
+} SMARTSHIFT_VERSION_e;
+
+typedef enum {
+ FOPT_CALC_AC_CALC_DC,
+ FOPT_PPTABLE_AC_CALC_DC,
+ FOPT_CALC_AC_PPTABLE_DC,
+ FOPT_PPTABLE_AC_PPTABLE_DC,
+} FOPT_CALC_e;
+
+typedef enum {
+ DRAM_BIT_WIDTH_DISABLED = 0,
+ DRAM_BIT_WIDTH_X_8 = 8,
+ DRAM_BIT_WIDTH_X_16 = 16,
+ DRAM_BIT_WIDTH_X_32 = 32,
+ DRAM_BIT_WIDTH_X_64 = 64,
+ DRAM_BIT_WIDTH_X_128 = 128,
+ DRAM_BIT_WIDTH_COUNT,
+} DRAM_BIT_WIDTH_TYPE_e;
+
+//I2C Interface
+#define NUM_I2C_CONTROLLERS 8
+
+#define I2C_CONTROLLER_ENABLED 1
+#define I2C_CONTROLLER_DISABLED 0
+
+#define MAX_SW_I2C_COMMANDS 24
+
+typedef enum {
+ I2C_CONTROLLER_PORT_0 = 0, //CKSVII2C0
+ I2C_CONTROLLER_PORT_1 = 1, //CKSVII2C1
+ I2C_CONTROLLER_PORT_COUNT,
+} I2cControllerPort_e;
+
+typedef enum {
+ I2C_CONTROLLER_NAME_VR_GFX = 0,
+ I2C_CONTROLLER_NAME_VR_SOC,
+ I2C_CONTROLLER_NAME_VR_VMEMP,
+ I2C_CONTROLLER_NAME_VR_VDDIO,
+ I2C_CONTROLLER_NAME_LIQUID0,
+ I2C_CONTROLLER_NAME_LIQUID1,
+ I2C_CONTROLLER_NAME_PLX,
+ I2C_CONTROLLER_NAME_OTHER,
+ I2C_CONTROLLER_NAME_COUNT,
+} I2cControllerName_e;
+
+typedef enum {
+ I2C_CONTROLLER_THROTTLER_TYPE_NONE = 0,
+ I2C_CONTROLLER_THROTTLER_VR_GFX,
+ I2C_CONTROLLER_THROTTLER_VR_SOC,
+ I2C_CONTROLLER_THROTTLER_VR_VMEMP,
+ I2C_CONTROLLER_THROTTLER_VR_VDDIO,
+ I2C_CONTROLLER_THROTTLER_LIQUID0,
+ I2C_CONTROLLER_THROTTLER_LIQUID1,
+ I2C_CONTROLLER_THROTTLER_PLX,
+ I2C_CONTROLLER_THROTTLER_INA3221,
+ I2C_CONTROLLER_THROTTLER_COUNT,
+} I2cControllerThrottler_e;
+
+typedef enum {
+ I2C_CONTROLLER_PROTOCOL_VR_XPDE132G5,
+ I2C_CONTROLLER_PROTOCOL_VR_IR35217,
+ I2C_CONTROLLER_PROTOCOL_TMP_TMP102A,
+ I2C_CONTROLLER_PROTOCOL_INA3221,
+ I2C_CONTROLLER_PROTOCOL_COUNT,
+} I2cControllerProtocol_e;
+
+typedef struct {
+ uint8_t Enabled;
+ uint8_t Speed;
+ uint8_t SlaveAddress;
+ uint8_t ControllerPort;
+ uint8_t ControllerName;
+ uint8_t ThermalThrotter;
+ uint8_t I2cProtocol;
+ uint8_t PaddingConfig;
+} I2cControllerConfig_t;
+
+typedef enum {
+ I2C_PORT_SVD_SCL = 0,
+ I2C_PORT_GPIO,
+} I2cPort_e;
+
+typedef enum {
+ I2C_SPEED_FAST_50K = 0, //50 Kbits/s
+ I2C_SPEED_FAST_100K, //100 Kbits/s
+ I2C_SPEED_FAST_400K, //400 Kbits/s
+ I2C_SPEED_FAST_PLUS_1M, //1 Mbits/s (in fast mode)
+ I2C_SPEED_HIGH_1M, //1 Mbits/s (in high speed mode)
+ I2C_SPEED_HIGH_2M, //2.3 Mbits/s
+ I2C_SPEED_COUNT,
+} I2cSpeed_e;
+
+typedef enum {
+ I2C_CMD_READ = 0,
+ I2C_CMD_WRITE,
+ I2C_CMD_COUNT,
+} I2cCmdType_e;
+
+#define CMDCONFIG_STOP_BIT 0
+#define CMDCONFIG_RESTART_BIT 1
+#define CMDCONFIG_READWRITE_BIT 2 //bit should be 0 for read, 1 for write
+
+#define CMDCONFIG_STOP_MASK (1 << CMDCONFIG_STOP_BIT)
+#define CMDCONFIG_RESTART_MASK (1 << CMDCONFIG_RESTART_BIT)
+#define CMDCONFIG_READWRITE_MASK (1 << CMDCONFIG_READWRITE_BIT)
+
+typedef struct {
+ uint8_t ReadWriteData; //Return data for read. Data to send for write
+ uint8_t CmdConfig; //Includes whether associated command should have a stop or restart command, and is a read or write
+} SwI2cCmd_t; //SW I2C Command Table
+
+typedef struct {
+ uint8_t I2CcontrollerPort; //CKSVII2C0(0) or //CKSVII2C1(1)
+ uint8_t I2CSpeed; //Use I2cSpeed_e to indicate speed to select
+ uint8_t SlaveAddress; //Slave address of device
+ uint8_t NumCmds; //Number of commands
+
+ SwI2cCmd_t SwI2cCmds[MAX_SW_I2C_COMMANDS];
+} SwI2cRequest_t; // SW I2C Request Table
+
+typedef struct {
+ SwI2cRequest_t SwI2cRequest;
+
+ uint32_t Spare[8];
+ uint32_t MmHubPadding[8]; // SMU internal use
+} SwI2cRequestExternal_t;
+
+typedef struct {
+ uint64_t mca_umc_status;
+ uint64_t mca_umc_addr;
+
+ uint16_t ce_count_lo_chip;
+ uint16_t ce_count_hi_chip;
+
+ uint32_t eccPadding;
+} EccInfo_t;
+
+typedef struct {
+ EccInfo_t EccInfo[24];
+} EccInfoTable_t;
+
+//D3HOT sequences
+typedef enum {
+ BACO_SEQUENCE,
+ MSR_SEQUENCE,
+ BAMACO_SEQUENCE,
+ ULPS_SEQUENCE,
+ D3HOT_SEQUENCE_COUNT,
+} D3HOTSequence_e;
+
+//This is aligned with RSMU PGFSM Register Mapping
+typedef enum {
+ PG_DYNAMIC_MODE = 0,
+ PG_STATIC_MODE,
+} PowerGatingMode_e;
+
+//This is aligned with RSMU PGFSM Register Mapping
+typedef enum {
+ PG_POWER_DOWN = 0,
+ PG_POWER_UP,
+} PowerGatingSettings_e;
+
+typedef struct {
+ uint32_t a; // store in IEEE float format in this variable
+ uint32_t b; // store in IEEE float format in this variable
+ uint32_t c; // store in IEEE float format in this variable
+} QuadraticInt_t;
+
+typedef struct {
+ uint32_t m; // store in IEEE float format in this variable
+ uint32_t b; // store in IEEE float format in this variable
+} LinearInt_t;
+
+typedef struct {
+ uint32_t a; // store in IEEE float format in this variable
+ uint32_t b; // store in IEEE float format in this variable
+ uint32_t c; // store in IEEE float format in this variable
+} DroopInt_t;
+
+typedef enum {
+ DCS_ARCH_DISABLED,
+ DCS_ARCH_FADCS,
+ DCS_ARCH_ASYNC,
+} DCS_ARCH_e;
+
+//Only Clks that have DPM descriptors are listed here
+typedef enum {
+ PPCLK_GFXCLK = 0,
+ PPCLK_SOCCLK,
+ PPCLK_UCLK,
+ PPCLK_FCLK,
+ PPCLK_DCLK_0,
+ PPCLK_VCLK_0,
+ PPCLK_DCLK_1,
+ PPCLK_VCLK_1,
+ PPCLK_DISPCLK,
+ PPCLK_DPPCLK,
+ PPCLK_DPREFCLK,
+ PPCLK_DCFCLK,
+ PPCLK_DTBCLK,
+ PPCLK_COUNT,
+} PPCLK_e;
+
+typedef enum {
+ VOLTAGE_MODE_PPTABLE = 0,
+ VOLTAGE_MODE_FUSES,
+ VOLTAGE_MODE_COUNT,
+} VOLTAGE_MODE_e;
+
+
+typedef enum {
+ AVFS_VOLTAGE_GFX = 0,
+ AVFS_VOLTAGE_SOC,
+ AVFS_VOLTAGE_COUNT,
+} AVFS_VOLTAGE_TYPE_e;
+
+typedef enum {
+ AVFS_TEMP_COLD = 0,
+ AVFS_TEMP_HOT,
+ AVFS_TEMP_COUNT,
+} AVFS_TEMP_e;
+
+typedef enum {
+ AVFS_D_G,
+ AVFS_D_M_B,
+ AVFS_D_M_S,
+ AVFS_D_COUNT,
+} AVFS_D_e;
+
+typedef enum {
+ UCLK_DIV_BY_1 = 0,
+ UCLK_DIV_BY_2,
+ UCLK_DIV_BY_4,
+ UCLK_DIV_BY_8,
+} UCLK_DIV_e;
+
+typedef enum {
+ GPIO_INT_POLARITY_ACTIVE_LOW = 0,
+ GPIO_INT_POLARITY_ACTIVE_HIGH,
+} GpioIntPolarity_e;
+
+typedef enum {
+ PWR_CONFIG_TDP = 0,
+ PWR_CONFIG_TGP,
+ PWR_CONFIG_TCP_ESTIMATED,
+ PWR_CONFIG_TCP_MEASURED,
+} PwrConfig_e;
+
+typedef struct {
+ uint8_t Padding;
+ uint8_t SnapToDiscrete; // 0 - Fine grained DPM, 1 - Discrete DPM
+ uint8_t NumDiscreteLevels; // Set to 2 (Fmin, Fmax) when using fine grained DPM, otherwise set to # discrete levels used
+ uint8_t CalculateFopt; // Indication whether FW should calculate Fopt or use values below. Reference FOPT_CALC_e
+ LinearInt_t ConversionToAvfsClk; // Transfer function to AVFS Clock (GHz->GHz)
+ uint32_t Padding3[3];
+ uint16_t Padding4;
+ uint16_t FoptimalDc; //Foptimal frequency in DC power mode.
+ uint16_t FoptimalAc; //Foptimal frequency in AC power mode.
+ uint16_t Padding2;
+} DpmDescriptor_t;
+
+typedef enum {
+ PPT_THROTTLER_PPT0,
+ PPT_THROTTLER_PPT1,
+ PPT_THROTTLER_PPT2,
+ PPT_THROTTLER_PPT3,
+ PPT_THROTTLER_COUNT
+} PPT_THROTTLER_e;
+
+typedef enum {
+ TEMP_EDGE,
+ TEMP_HOTSPOT,
+ TEMP_HOTSPOT_G,
+ TEMP_HOTSPOT_M,
+ TEMP_MEM,
+ TEMP_VR_GFX,
+ TEMP_VR_MEM0,
+ TEMP_VR_MEM1,
+ TEMP_VR_SOC,
+ TEMP_VR_U,
+ TEMP_LIQUID0,
+ TEMP_LIQUID1,
+ TEMP_PLX,
+ TEMP_COUNT,
+} TEMP_e;
+
+typedef enum {
+ TDC_THROTTLER_GFX,
+ TDC_THROTTLER_SOC,
+ TDC_THROTTLER_U,
+ TDC_THROTTLER_COUNT
+} TDC_THROTTLER_e;
+
+typedef enum {
+ SVI_PLANE_GFX,
+ SVI_PLANE_SOC,
+ SVI_PLANE_VMEMP,
+ SVI_PLANE_VDDIO_MEM,
+ SVI_PLANE_U,
+ SVI_PLANE_COUNT,
+} SVI_PLANE_e;
+
+typedef enum {
+ PMFW_VOLT_PLANE_GFX,
+ PMFW_VOLT_PLANE_SOC,
+ PMFW_VOLT_PLANE_COUNT
+} PMFW_VOLT_PLANE_e;
+
+typedef enum {
+ CUSTOMER_VARIANT_ROW,
+ CUSTOMER_VARIANT_FALCON,
+ CUSTOMER_VARIANT_COUNT,
+} CUSTOMER_VARIANT_e;
+
+typedef enum {
+ POWER_SOURCE_AC,
+ POWER_SOURCE_DC,
+ POWER_SOURCE_COUNT,
+} POWER_SOURCE_e;
+
+typedef enum {
+ MEM_VENDOR_SAMSUNG,
+ MEM_VENDOR_INFINEON,
+ MEM_VENDOR_ELPIDA,
+ MEM_VENDOR_ETRON,
+ MEM_VENDOR_NANYA,
+ MEM_VENDOR_HYNIX,
+ MEM_VENDOR_MOSEL,
+ MEM_VENDOR_WINBOND,
+ MEM_VENDOR_ESMT,
+ MEM_VENDOR_PLACEHOLDER0,
+ MEM_VENDOR_PLACEHOLDER1,
+ MEM_VENDOR_PLACEHOLDER2,
+ MEM_VENDOR_PLACEHOLDER3,
+ MEM_VENDOR_PLACEHOLDER4,
+ MEM_VENDOR_PLACEHOLDER5,
+ MEM_VENDOR_MICRON,
+ MEM_VENDOR_COUNT,
+} MEM_VENDOR_e;
+
+typedef enum {
+ PP_GRTAVFS_HW_CPO_CTL_ZONE0,
+ PP_GRTAVFS_HW_CPO_CTL_ZONE1,
+ PP_GRTAVFS_HW_CPO_CTL_ZONE2,
+ PP_GRTAVFS_HW_CPO_CTL_ZONE3,
+ PP_GRTAVFS_HW_CPO_CTL_ZONE4,
+ PP_GRTAVFS_HW_CPO_EN_0_31_ZONE0,
+ PP_GRTAVFS_HW_CPO_EN_32_63_ZONE0,
+ PP_GRTAVFS_HW_CPO_EN_0_31_ZONE1,
+ PP_GRTAVFS_HW_CPO_EN_32_63_ZONE1,
+ PP_GRTAVFS_HW_CPO_EN_0_31_ZONE2,
+ PP_GRTAVFS_HW_CPO_EN_32_63_ZONE2,
+ PP_GRTAVFS_HW_CPO_EN_0_31_ZONE3,
+ PP_GRTAVFS_HW_CPO_EN_32_63_ZONE3,
+ PP_GRTAVFS_HW_CPO_EN_0_31_ZONE4,
+ PP_GRTAVFS_HW_CPO_EN_32_63_ZONE4,
+ PP_GRTAVFS_HW_ZONE0_VF,
+ PP_GRTAVFS_HW_ZONE1_VF1,
+ PP_GRTAVFS_HW_ZONE2_VF2,
+ PP_GRTAVFS_HW_ZONE3_VF3,
+ PP_GRTAVFS_HW_VOLTAGE_GB,
+ PP_GRTAVFS_HW_CPOSCALINGCTRL_ZONE0,
+ PP_GRTAVFS_HW_CPOSCALINGCTRL_ZONE1,
+ PP_GRTAVFS_HW_CPOSCALINGCTRL_ZONE2,
+ PP_GRTAVFS_HW_CPOSCALINGCTRL_ZONE3,
+ PP_GRTAVFS_HW_CPOSCALINGCTRL_ZONE4,
+ PP_GRTAVFS_HW_RESERVED_0,
+ PP_GRTAVFS_HW_RESERVED_1,
+ PP_GRTAVFS_HW_RESERVED_2,
+ PP_GRTAVFS_HW_RESERVED_3,
+ PP_GRTAVFS_HW_RESERVED_4,
+ PP_GRTAVFS_HW_RESERVED_5,
+ PP_GRTAVFS_HW_RESERVED_6,
+ PP_GRTAVFS_HW_FUSE_COUNT,
+} PP_GRTAVFS_HW_FUSE_e;
+
+typedef enum {
+ PP_GRTAVFS_FW_COMMON_PPVMIN_Z1_HOT_T0,
+ PP_GRTAVFS_FW_COMMON_PPVMIN_Z1_COLD_T0,
+ PP_GRTAVFS_FW_COMMON_PPVMIN_Z2_HOT_T0,
+ PP_GRTAVFS_FW_COMMON_PPVMIN_Z2_COLD_T0,
+ PP_GRTAVFS_FW_COMMON_PPVMIN_Z3_HOT_T0,
+ PP_GRTAVFS_FW_COMMON_PPVMIN_Z3_COLD_T0,
+ PP_GRTAVFS_FW_COMMON_PPVMIN_Z4_HOT_T0,
+ PP_GRTAVFS_FW_COMMON_PPVMIN_Z4_COLD_T0,
+ PP_GRTAVFS_FW_COMMON_SRAM_RM_Z0,
+ PP_GRTAVFS_FW_COMMON_SRAM_RM_Z1,
+ PP_GRTAVFS_FW_COMMON_SRAM_RM_Z2,
+ PP_GRTAVFS_FW_COMMON_SRAM_RM_Z3,
+ PP_GRTAVFS_FW_COMMON_SRAM_RM_Z4,
+ PP_GRTAVFS_FW_COMMON_FUSE_COUNT,
+} PP_GRTAVFS_FW_COMMON_FUSE_e;
+
+typedef enum {
+ PP_GRTAVFS_FW_SEP_FUSE_GB1_PWL_VOLTAGE_NEG_1,
+ PP_GRTAVFS_FW_SEP_FUSE_GB1_PWL_VOLTAGE_0,
+ PP_GRTAVFS_FW_SEP_FUSE_GB1_PWL_VOLTAGE_1,
+ PP_GRTAVFS_FW_SEP_FUSE_GB1_PWL_VOLTAGE_2,
+ PP_GRTAVFS_FW_SEP_FUSE_GB1_PWL_VOLTAGE_3,
+ PP_GRTAVFS_FW_SEP_FUSE_GB1_PWL_VOLTAGE_4,
+ PP_GRTAVFS_FW_SEP_FUSE_GB2_PWL_VOLTAGE_NEG_1,
+ PP_GRTAVFS_FW_SEP_FUSE_GB2_PWL_VOLTAGE_0,
+ PP_GRTAVFS_FW_SEP_FUSE_GB2_PWL_VOLTAGE_1,
+ PP_GRTAVFS_FW_SEP_FUSE_GB2_PWL_VOLTAGE_2,
+ PP_GRTAVFS_FW_SEP_FUSE_GB2_PWL_VOLTAGE_3,
+ PP_GRTAVFS_FW_SEP_FUSE_GB2_PWL_VOLTAGE_4,
+ PP_GRTAVFS_FW_SEP_FUSE_VF_NEG_1_FREQUENCY,
+ PP_GRTAVFS_FW_SEP_FUSE_VF4_FREQUENCY,
+ PP_GRTAVFS_FW_SEP_FUSE_FREQUENCY_TO_COUNT_SCALER_0,
+ PP_GRTAVFS_FW_SEP_FUSE_FREQUENCY_TO_COUNT_SCALER_1,
+ PP_GRTAVFS_FW_SEP_FUSE_FREQUENCY_TO_COUNT_SCALER_2,
+ PP_GRTAVFS_FW_SEP_FUSE_FREQUENCY_TO_COUNT_SCALER_3,
+ PP_GRTAVFS_FW_SEP_FUSE_FREQUENCY_TO_COUNT_SCALER_4,
+ PP_GRTAVFS_FW_SEP_FUSE_COUNT,
+} PP_GRTAVFS_FW_SEP_FUSE_e;
+
+#define PP_NUM_RTAVFS_PWL_ZONES 5
+
+
+
+// VBIOS or PPLIB configures telemetry slope and offset. Only slope expected to be set for SVI3
+// Slope Q1.7, Offset Q1.2
+typedef struct {
+ int8_t Offset; // in Amps
+ uint8_t Padding;
+ uint16_t MaxCurrent; // in Amps
+} SviTelemetryScale_t;
+
+#define PP_NUM_OD_VF_CURVE_POINTS PP_NUM_RTAVFS_PWL_ZONES + 1
+
+
+#define PP_OD_FEATURE_VF_CURVE_BIT 0
+#define PP_OD_FEATURE_VMAX_BIT 1
+#define PP_OD_FEATURE_PPT_BIT 2
+#define PP_OD_FEATURE_FAN_CURVE_BIT 3
+#define PP_OD_FEATURE_FREQ_DETER_BIT 4
+#define PP_OD_FEATURE_FULL_CTRL_BIT 5
+#define PP_OD_FEATURE_TDC_BIT 6
+#define PP_OD_FEATURE_GFXCLK_BIT 7
+#define PP_OD_FEATURE_UCLK_BIT 8
+
+typedef enum {
+ PP_OD_POWER_FEATURE_ALWAYS_ENABLED,
+ PP_OD_POWER_FEATURE_DISABLED_WHILE_GAMING,
+ PP_OD_POWER_FEATURE_ALWAYS_DISABLED,
+} PP_OD_POWER_FEATURE_e;
+
+typedef struct {
+ uint32_t FeatureCtrlMask;
+
+ //Voltage control
+ int16_t VoltageOffsetPerZoneBoundary[PP_NUM_OD_VF_CURVE_POINTS];
+ uint16_t VddGfxVmax; // in mV
+
+ uint8_t IdlePwrSavingFeaturesCtrl;
+ uint8_t RuntimePwrSavingFeaturesCtrl;
+
+ //Frequency changes
+ uint16_t GfxclkFmin; // MHz
+ uint16_t GfxclkFmax; // MHz
+ uint16_t UclkFmin; // MHz
+ uint16_t UclkFmax; // MHz
+
+ //PPT
+ int16_t Ppt; // %
+ int16_t Tdc;
+
+ //Fan control
+ uint8_t FanLinearPwmPoints[NUM_OD_FAN_MAX_POINTS];
+ uint8_t FanLinearTempPoints[NUM_OD_FAN_MAX_POINTS];
+ uint16_t FanMaximumRpm;
+ uint16_t FanMinimumPwm;
+ uint16_t FanAcousticLimitRpm;
+ uint16_t FanTargetTemperature; // Degree Celcius
+ uint8_t FanZeroRpmEnable;
+ uint8_t FanZeroRpmStopTemp;
+ uint8_t FanMode;
+ uint8_t Padding[1];
+
+
+ uint32_t Spare[13];
+ uint32_t MmHubPadding[8]; // SMU internal use. Adding here instead of external as a workaround
+} OverDriveTable_t;
+
+typedef struct {
+ OverDriveTable_t OverDriveTable;
+
+} OverDriveTableExternal_t;
+
+typedef struct {
+ uint32_t FeatureCtrlMask;
+
+ int16_t VoltageOffsetPerZoneBoundary;
+ uint16_t VddGfxVmax; // in mV
+
+ uint8_t IdlePwrSavingFeaturesCtrl;
+ uint8_t RuntimePwrSavingFeaturesCtrl;
+
+ uint16_t GfxclkFmin; // MHz
+ uint16_t GfxclkFmax; // MHz
+ uint16_t UclkFmin; // MHz
+ uint16_t UclkFmax; // MHz
+
+ //PPT
+ int16_t Ppt; // %
+ int16_t Tdc;
+
+ uint8_t FanLinearPwmPoints;
+ uint8_t FanLinearTempPoints;
+ uint16_t FanMaximumRpm;
+ uint16_t FanMinimumPwm;
+ uint16_t FanAcousticLimitRpm;
+ uint16_t FanTargetTemperature; // Degree Celcius
+ uint8_t FanZeroRpmEnable;
+ uint8_t FanZeroRpmStopTemp;
+ uint8_t FanMode;
+ uint8_t Padding[1];
+
+
+ uint32_t Spare[13];
+
+} OverDriveLimits_t;
+
+
+typedef enum {
+ BOARD_GPIO_SMUIO_0,
+ BOARD_GPIO_SMUIO_1,
+ BOARD_GPIO_SMUIO_2,
+ BOARD_GPIO_SMUIO_3,
+ BOARD_GPIO_SMUIO_4,
+ BOARD_GPIO_SMUIO_5,
+ BOARD_GPIO_SMUIO_6,
+ BOARD_GPIO_SMUIO_7,
+ BOARD_GPIO_SMUIO_8,
+ BOARD_GPIO_SMUIO_9,
+ BOARD_GPIO_SMUIO_10,
+ BOARD_GPIO_SMUIO_11,
+ BOARD_GPIO_SMUIO_12,
+ BOARD_GPIO_SMUIO_13,
+ BOARD_GPIO_SMUIO_14,
+ BOARD_GPIO_SMUIO_15,
+ BOARD_GPIO_SMUIO_16,
+ BOARD_GPIO_SMUIO_17,
+ BOARD_GPIO_SMUIO_18,
+ BOARD_GPIO_SMUIO_19,
+ BOARD_GPIO_SMUIO_20,
+ BOARD_GPIO_SMUIO_21,
+ BOARD_GPIO_SMUIO_22,
+ BOARD_GPIO_SMUIO_23,
+ BOARD_GPIO_SMUIO_24,
+ BOARD_GPIO_SMUIO_25,
+ BOARD_GPIO_SMUIO_26,
+ BOARD_GPIO_SMUIO_27,
+ BOARD_GPIO_SMUIO_28,
+ BOARD_GPIO_SMUIO_29,
+ BOARD_GPIO_SMUIO_30,
+ BOARD_GPIO_SMUIO_31,
+ MAX_BOARD_GPIO_SMUIO_NUM,
+ BOARD_GPIO_DC_GEN_A,
+ BOARD_GPIO_DC_GEN_B,
+ BOARD_GPIO_DC_GEN_C,
+ BOARD_GPIO_DC_GEN_D,
+ BOARD_GPIO_DC_GEN_E,
+ BOARD_GPIO_DC_GEN_F,
+ BOARD_GPIO_DC_GEN_G,
+ BOARD_GPIO_DC_GENLK_CLK,
+ BOARD_GPIO_DC_GENLK_VSYNC,
+ BOARD_GPIO_DC_SWAPLOCK_A,
+ BOARD_GPIO_DC_SWAPLOCK_B,
+} BOARD_GPIO_TYPE_e;
+
+#define INVALID_BOARD_GPIO 0xFF
+
+
+typedef struct {
+ //PLL 0
+ uint16_t InitGfxclk_bypass;
+ uint16_t InitSocclk;
+ uint16_t InitMp0clk;
+ uint16_t InitMpioclk;
+ uint16_t InitSmnclk;
+ uint16_t InitUcpclk;
+ uint16_t InitCsrclk;
+ //PLL 1
+
+ uint16_t InitDprefclk;
+ uint16_t InitDcfclk;
+ uint16_t InitDtbclk;
+ //PLL 2
+ uint16_t InitDclk; //assume same DCLK/VCLK for both instances
+ uint16_t InitVclk;
+ // PLL 3
+ uint16_t InitUsbdfsclk;
+ uint16_t InitMp1clk;
+ uint16_t InitLclk;
+ uint16_t InitBaco400clk_bypass;
+ uint16_t InitBaco1200clk_bypass;
+ uint16_t InitBaco700clk_bypass;
+ // PLL 4
+ uint16_t InitFclk;
+ // PLL 5
+ uint16_t InitGfxclk_clkb;
+
+ //PLL 6
+ uint8_t InitUclkDPMState; // =0,1,2,3, frequency from FreqTableUclk
+
+ uint8_t Padding[3];
+
+ uint32_t InitVcoFreqPll0;
+ uint32_t InitVcoFreqPll1;
+ uint32_t InitVcoFreqPll2;
+ uint32_t InitVcoFreqPll3;
+ uint32_t InitVcoFreqPll4;
+ uint32_t InitVcoFreqPll5;
+ uint32_t InitVcoFreqPll6;
+
+ //encoding will change depending on SVI2/SVI3
+ uint16_t InitGfx; // In mV(Q2) , should be 0?
+ uint16_t InitSoc; // In mV(Q2)
+ uint16_t InitU; // In Mv(Q2) not applicable
+
+ uint16_t Padding2;
+
+ uint32_t Spare[8];
+
+} BootValues_t;
+
+
+typedef struct {
+ uint16_t Power[PPT_THROTTLER_COUNT][POWER_SOURCE_COUNT]; // Watts
+ uint16_t Tdc[TDC_THROTTLER_COUNT]; // Amps
+
+ uint16_t Temperature[TEMP_COUNT]; // Celsius
+
+ uint8_t PwmLimitMin;
+ uint8_t PwmLimitMax;
+ uint8_t FanTargetTemperature;
+ uint8_t Spare1[1];
+
+ uint16_t AcousticTargetRpmThresholdMin;
+ uint16_t AcousticTargetRpmThresholdMax;
+
+ uint16_t AcousticLimitRpmThresholdMin;
+ uint16_t AcousticLimitRpmThresholdMax;
+
+ uint16_t PccLimitMin;
+ uint16_t PccLimitMax;
+
+ uint16_t FanStopTempMin;
+ uint16_t FanStopTempMax;
+ uint16_t FanStartTempMin;
+ uint16_t FanStartTempMax;
+
+ uint32_t Spare[12];
+
+} MsgLimits_t;
+
+typedef struct {
+ uint16_t BaseClockAc;
+ uint16_t GameClockAc;
+ uint16_t BoostClockAc;
+ uint16_t BaseClockDc;
+ uint16_t GameClockDc;
+ uint16_t BoostClockDc;
+
+ uint32_t Reserved[4];
+} DriverReportedClocks_t;
+
+typedef struct {
+ uint8_t DcBtcEnabled;
+ uint8_t Padding[3];
+
+ uint16_t DcTol; // mV Q2
+ uint16_t DcBtcGb; // mV Q2
+
+ uint16_t DcBtcMin; // mV Q2
+ uint16_t DcBtcMax; // mV Q2
+
+ LinearInt_t DcBtcGbScalar;
+
+} AvfsDcBtcParams_t;
+
+typedef struct {
+ uint16_t AvfsTemp[AVFS_TEMP_COUNT]; //in degrees C
+ uint16_t VftFMin; // in MHz
+ uint16_t VInversion; // in mV Q2
+ QuadraticInt_t qVft[AVFS_TEMP_COUNT];
+ QuadraticInt_t qAvfsGb;
+ QuadraticInt_t qAvfsGb2;
+} AvfsFuseOverride_t;
+
+typedef struct {
+ // SECTION: Version
+
+ uint32_t Version; // should be unique to each SKU(i.e if any value changes in below structure then this value must be different)
+
+ // SECTION: Feature Control
+ uint32_t FeaturesToRun[NUM_FEATURES / 32]; // Features that PMFW will attempt to enable. Use FEATURE_*_BIT as mapping
+
+ // SECTION: Miscellaneous Configuration
+ uint8_t TotalPowerConfig; // Determines how PMFW calculates the power. Use defines from PwrConfig_e
+ uint8_t CustomerVariant; //To specify if this PPTable is intended for a particular customer. Use defines from CUSTOMER_VARIANT_e
+ uint8_t MemoryTemperatureTypeMask; // Bit mapping indicating which methods of memory temperature reading are enabled. Use defines from MEM_TEMP_*BIT
+ uint8_t SmartShiftVersion; // Determine what SmartShift feature version is supported Use defines from SMARTSHIFT_VERSION_e
+
+ // SECTION: Infrastructure Limits
+ uint16_t SocketPowerLimitAc[PPT_THROTTLER_COUNT]; // In Watts. Power limit that PMFW attempts to control to in AC mode. Multiple limits supported
+ uint16_t SocketPowerLimitDc[PPT_THROTTLER_COUNT]; // In Watts. Power limit that PMFW attempts to control to in DC mode. Multiple limits supported
+
+ uint16_t SocketPowerLimitSmartShift2; // In Watts. Power limit used SmartShift
+
+ //if set to 1, SocketPowerLimitAc and SocketPowerLimitDc will be interpreted as legacy programs(i.e absolute power). If 0, all except index 0 will be scalars
+ //relative index 0
+ uint8_t EnableLegacyPptLimit;
+ uint8_t UseInputTelemetry; //applicable to SVI3 only and only to be set if VRs support
+ uint8_t SmartShiftMinReportedPptinDcs; //minimum possible active power consumption for this SKU. Used for SmartShift power reporting
+
+ uint8_t PaddingPpt[1];
+
+ uint16_t VrTdcLimit[TDC_THROTTLER_COUNT]; // In Amperes. Current limit associated with VR regulator maximum temperature
+
+ uint16_t PlatformTdcLimit[TDC_THROTTLER_COUNT]; // In Amperes. Current limit associated with platform maximum temperature per VR current rail
+
+ uint16_t TemperatureLimit[TEMP_COUNT]; // In degrees Celsius. Temperature limit associated with each input
+
+ uint16_t HwCtfTempLimit; // In degrees Celsius. Temperature above which HW will trigger CTF. Consumed by VBIOS only
+
+ uint16_t PaddingInfra;
+
+ // Per year normalized Vmax state failure rates (sum of the two domains divided by life time in years)
+ uint32_t FitControllerFailureRateLimit; //in IEEE float
+ //Expected GFX Duty Cycle at Vmax.
+ uint32_t FitControllerGfxDutyCycle; // in IEEE float
+ //Expected SOC Duty Cycle at Vmax.
+ uint32_t FitControllerSocDutyCycle; // in IEEE float
+
+ //This offset will be deducted from the controller output to before it goes through the SOC Vset limiter block.
+ uint32_t FitControllerSocOffset; //in IEEE float
+
+ uint32_t GfxApccPlusResidencyLimit; // Percentage value. Used by APCC+ controller to control PCC residency to some value
+
+ // SECTION: Throttler settings
+ uint32_t ThrottlerControlMask; // See THROTTLER_*_BIT for mapping
+
+ // SECTION: FW DSTATE Settings
+ uint32_t FwDStateMask; // See FW_DSTATE_*_BIT for mapping
+
+ // SECTION: Voltage Control Parameters
+ uint16_t UlvVoltageOffset[PMFW_VOLT_PLANE_COUNT]; // In mV(Q2). ULV offset used in either GFX_ULV or SOC_ULV(part of FW_DSTATE)
+
+ uint16_t UlvVoltageOffsetU; // In mV(Q2). ULV offset used in either U_ULV(part of FW_DSTATE)
+ uint16_t DeepUlvVoltageOffsetSoc; // In mV(Q2) Long Idle Vmin (deep ULV), for VDD_SOC as part of FW_DSTATE
+
+ // Voltage Limits
+ uint16_t DefaultMaxVoltage[PMFW_VOLT_PLANE_COUNT]; // In mV(Q2) Maximum voltage without FIT controller enabled
+ uint16_t BoostMaxVoltage[PMFW_VOLT_PLANE_COUNT]; // In mV(Q2) Maximum voltage with FIT controller enabled
+
+ //Vmin Optimizations
+ int16_t VminTempHystersis[PMFW_VOLT_PLANE_COUNT]; // Celsius Temperature hysteresis for switching between low/high temperature values for Vmin
+ int16_t VminTempThreshold[PMFW_VOLT_PLANE_COUNT]; // Celsius Temperature threshold for switching between low/high temperature values for Vmin
+ uint16_t Vmin_Hot_T0[PMFW_VOLT_PLANE_COUNT]; //In mV(Q2) Initial (pre-aging) Vset to be used at hot.
+ uint16_t Vmin_Cold_T0[PMFW_VOLT_PLANE_COUNT]; //In mV(Q2) Initial (pre-aging) Vset to be used at cold.
+ uint16_t Vmin_Hot_Eol[PMFW_VOLT_PLANE_COUNT]; //In mV(Q2) End-of-life Vset to be used at hot.
+ uint16_t Vmin_Cold_Eol[PMFW_VOLT_PLANE_COUNT]; //In mV(Q2) End-of-life Vset to be used at cold.
+ uint16_t Vmin_Aging_Offset[PMFW_VOLT_PLANE_COUNT]; //In mV(Q2) Worst-case aging margin
+ uint16_t Vmin_Plat_Offset_Hot[PMFW_VOLT_PLANE_COUNT]; //In mV(Q2) Platform offset apply to T0 Hot
+ uint16_t Vmin_Plat_Offset_Cold[PMFW_VOLT_PLANE_COUNT]; //In mV(Q2) Platform offset apply to T0 Cold
+
+ //This is a fixed/minimum VMIN aging degradation offset which is applied at T0. This reflects the minimum amount of aging already accounted for.
+ uint16_t VcBtcFixedVminAgingOffset[PMFW_VOLT_PLANE_COUNT];
+ //Linear offset or GB term to account for mis-correlation between PSM and Vmin shift trends across parts.
+ uint16_t VcBtcVmin2PsmDegrationGb[PMFW_VOLT_PLANE_COUNT];
+ //Scalar coefficient of the PSM aging degradation function
+ uint32_t VcBtcPsmA[PMFW_VOLT_PLANE_COUNT]; // A_PSM
+ //Exponential coefficient of the PSM aging degradation function
+ uint32_t VcBtcPsmB[PMFW_VOLT_PLANE_COUNT]; // B_PSM
+ //Scalar coefficient of the VMIN aging degradation function. Specified as worst case between hot and cold.
+ uint32_t VcBtcVminA[PMFW_VOLT_PLANE_COUNT]; // A_VMIN
+ //Exponential coefficient of the VMIN aging degradation function. Specified as worst case between hot and cold.
+ uint32_t VcBtcVminB[PMFW_VOLT_PLANE_COUNT]; // B_VMIN
+
+ uint8_t PerPartVminEnabled[PMFW_VOLT_PLANE_COUNT];
+ uint8_t VcBtcEnabled[PMFW_VOLT_PLANE_COUNT];
+
+ uint16_t SocketPowerLimitAcTau[PPT_THROTTLER_COUNT]; // Time constant of LPF in ms
+ uint16_t SocketPowerLimitDcTau[PPT_THROTTLER_COUNT]; // Time constant of LPF in ms
+
+ uint32_t SpareVmin[12];
+
+
+ //SECTION: DPM Configuration 1
+ DpmDescriptor_t DpmDescriptor[PPCLK_COUNT];
+
+ uint16_t FreqTableGfx [NUM_GFXCLK_DPM_LEVELS ]; // In MHz
+ uint16_t FreqTableVclk [NUM_VCLK_DPM_LEVELS ]; // In MHz
+ uint16_t FreqTableDclk [NUM_DCLK_DPM_LEVELS ]; // In MHz
+ uint16_t FreqTableSocclk [NUM_SOCCLK_DPM_LEVELS ]; // In MHz
+ uint16_t FreqTableUclk [NUM_UCLK_DPM_LEVELS ]; // In MHz
+ uint16_t FreqTableDispclk [NUM_DISPCLK_DPM_LEVELS ]; // In MHz
+ uint16_t FreqTableDppClk [NUM_DPPCLK_DPM_LEVELS ]; // In MHz
+ uint16_t FreqTableDprefclk [NUM_DPREFCLK_DPM_LEVELS]; // In MHz
+ uint16_t FreqTableDcfclk [NUM_DCFCLK_DPM_LEVELS ]; // In MHz
+ uint16_t FreqTableDtbclk [NUM_DTBCLK_DPM_LEVELS ]; // In MHz
+ uint16_t FreqTableFclk [NUM_FCLK_DPM_LEVELS ]; // In MHz
+
+ uint32_t DcModeMaxFreq [PPCLK_COUNT ]; // In MHz
+
+ // SECTION: DPM Configuration 2
+ uint16_t Mp0clkFreq [NUM_MP0CLK_DPM_LEVELS]; // in MHz
+ uint16_t Mp0DpmVoltage [NUM_MP0CLK_DPM_LEVELS]; // mV(Q2)
+
+ uint8_t GfxclkSpare[2];
+ uint16_t GfxclkFreqCap;
+
+ //GFX Idle Power Settings
+ uint16_t GfxclkFgfxoffEntry; // in Mhz
+ uint16_t GfxclkFgfxoffExitImu; // in Mhz
+ uint16_t GfxclkFgfxoffExitRlc; // in Mhz
+ uint16_t GfxclkThrottleClock; //Used primarily in DCS
+ uint8_t EnableGfxPowerStagesGpio; //Genlk_vsync GPIO flag used to control gfx power stages
+ uint8_t GfxIdlePadding;
+
+ uint8_t SmsRepairWRCKClkDivEn;
+ uint8_t SmsRepairWRCKClkDivVal;
+ uint8_t GfxOffEntryEarlyMGCGEn;
+ uint8_t GfxOffEntryForceCGCGEn;
+ uint8_t GfxOffEntryForceCGCGDelayEn;
+ uint8_t GfxOffEntryForceCGCGDelayVal; // in microseconds
+
+ uint16_t GfxclkFreqGfxUlv; // in MHz
+ uint8_t GfxIdlePadding2[2];
+
+ uint32_t GfxoffSpare[16];
+
+ // GFX GPO
+ uint32_t GfxGpoSpare[16];
+
+ // GFX DCS
+
+ uint16_t DcsGfxOffVoltage; //Voltage in mV(Q2) applied to VDDGFX when entering DCS GFXOFF phase
+ uint16_t PaddingDcs;
+
+ uint16_t DcsMinGfxOffTime; //Minimum amount of time PMFW shuts GFX OFF as part of GFX DCS phase
+ uint16_t DcsMaxGfxOffTime; //Maximum amount of time PMFW can shut GFX OFF as part of GFX DCS phase at a stretch.
+
+ uint32_t DcsMinCreditAccum; //Min amount of positive credit accumulation before waking GFX up as part of DCS.
+
+ uint16_t DcsExitHysteresis; //The min amount of time power credit accumulator should have a value > 0 before SMU exits the DCS throttling phase.
+ uint16_t DcsTimeout; //This is the amount of time SMU FW waits for RLC to put GFX into GFXOFF before reverting to the fallback mechanism of throttling GFXCLK to Fmin.
+
+
+ uint32_t DcsSpare[16];
+
+ // UCLK section
+ uint8_t UseStrobeModeOptimizations; //Set to indicate that FW should use strobe mode optimizations
+ uint8_t PaddingMem[3];
+
+ uint8_t UclkDpmPstates [NUM_UCLK_DPM_LEVELS]; // 4 DPM states, 0-P0, 1-P1, 2-P2, 3-P3.
+ uint8_t FreqTableUclkDiv [NUM_UCLK_DPM_LEVELS ]; // 0:Div-1, 1:Div-1/2, 2:Div-1/4, 3:Div-1/8
+
+ uint16_t MemVmempVoltage [NUM_UCLK_DPM_LEVELS]; // mV(Q2)
+ uint16_t MemVddioVoltage [NUM_UCLK_DPM_LEVELS]; // mV(Q2)
+
+ //FCLK Section
+
+ uint8_t FclkDpmUPstates[NUM_FCLK_DPM_LEVELS]; // U P-state ID associated with each FCLK DPM state.
+ uint16_t FclkDpmVddU[NUM_FCLK_DPM_LEVELS]; // mV(Q2) Vset U voltage associated with each FCLK DPM state.
+ uint16_t FclkDpmUSpeed[NUM_FCLK_DPM_LEVELS]; //U speed associated with each FCLK DPM state
+ uint16_t FclkDpmDisallowPstateFreq; //Frequency which FW will target when indicated that display config cannot support P-state. Set to 0 use FW calculated value
+ uint16_t PaddingFclk;
+
+ // Link DPM Settings
+ uint8_t PcieGenSpeed[NUM_LINK_LEVELS]; ///< 0:PciE-gen1 1:PciE-gen2 2:PciE-gen3 3:PciE-gen4
+ uint8_t PcieLaneCount[NUM_LINK_LEVELS]; ///< 1=x1, 2=x2, 3=x4, 4=x8, 5=x12, 6=x16
+ uint16_t LclkFreq[NUM_LINK_LEVELS];
+
+ // SECTION: Fan Control
+ uint16_t FanStopTemp[TEMP_COUNT]; //Celsius
+ uint16_t FanStartTemp[TEMP_COUNT]; //Celsius
+
+ uint16_t FanGain[TEMP_COUNT];
+ uint16_t FanGainPadding;
+
+ uint16_t FanPwmMin;
+ uint16_t AcousticTargetRpmThreshold;
+ uint16_t AcousticLimitRpmThreshold;
+ uint16_t FanMaximumRpm;
+ uint16_t MGpuAcousticLimitRpmThreshold;
+ uint16_t FanTargetGfxclk;
+ uint32_t TempInputSelectMask;
+ uint8_t FanZeroRpmEnable;
+ uint8_t FanTachEdgePerRev;
+ uint16_t FanTargetTemperature[TEMP_COUNT];
+
+ // The following are AFC override parameters. Leave at 0 to use FW defaults.
+ int16_t FuzzyFan_ErrorSetDelta;
+ int16_t FuzzyFan_ErrorRateSetDelta;
+ int16_t FuzzyFan_PwmSetDelta;
+ uint16_t FuzzyFan_Reserved;
+
+ uint16_t FwCtfLimit[TEMP_COUNT];
+
+ uint16_t IntakeTempEnableRPM;
+ int16_t IntakeTempOffsetTemp;
+ uint16_t IntakeTempReleaseTemp;
+ uint16_t IntakeTempHighIntakeAcousticLimit;
+ uint16_t IntakeTempAcouticLimitReleaseRate;
+
+ uint16_t FanStalledTempLimitOffset;
+ uint16_t FanStalledTriggerRpm;
+ uint16_t FanAbnormalTriggerRpm;
+ uint16_t FanPadding;
+
+ uint32_t FanSpare[14];
+
+ // SECTION: VDD_GFX AVFS
+
+ uint8_t OverrideGfxAvfsFuses;
+ uint8_t GfxAvfsPadding[3];
+
+ uint32_t L2HwRtAvfsFuses[PP_GRTAVFS_HW_FUSE_COUNT]; //see fusedoc for encoding
+ uint32_t SeHwRtAvfsFuses[PP_GRTAVFS_HW_FUSE_COUNT];
+
+ uint32_t CommonRtAvfs[PP_GRTAVFS_FW_COMMON_FUSE_COUNT];
+
+ uint32_t L2FwRtAvfsFuses[PP_GRTAVFS_FW_SEP_FUSE_COUNT];
+ uint32_t SeFwRtAvfsFuses[PP_GRTAVFS_FW_SEP_FUSE_COUNT];
+
+ uint32_t Droop_PWL_F[PP_NUM_RTAVFS_PWL_ZONES];
+ uint32_t Droop_PWL_a[PP_NUM_RTAVFS_PWL_ZONES];
+ uint32_t Droop_PWL_b[PP_NUM_RTAVFS_PWL_ZONES];
+ uint32_t Droop_PWL_c[PP_NUM_RTAVFS_PWL_ZONES];
+
+ uint32_t Static_PWL_Offset[PP_NUM_RTAVFS_PWL_ZONES];
+
+ uint32_t dGbV_dT_vmin;
+ uint32_t dGbV_dT_vmax;
+
+ //Unused: PMFW-9370
+ uint32_t V2F_vmin_range_low;
+ uint32_t V2F_vmin_range_high;
+ uint32_t V2F_vmax_range_low;
+ uint32_t V2F_vmax_range_high;
+
+ AvfsDcBtcParams_t DcBtcGfxParams;
+
+ uint32_t GfxAvfsSpare[32];
+
+ //SECTION: VDD_SOC AVFS
+
+ uint8_t OverrideSocAvfsFuses;
+ uint8_t MinSocAvfsRevision;
+ uint8_t SocAvfsPadding[2];
+
+ AvfsFuseOverride_t SocAvfsFuseOverride[AVFS_D_COUNT];
+
+ DroopInt_t dBtcGbSoc[AVFS_D_COUNT]; // GHz->V BtcGb
+
+ LinearInt_t qAgingGb[AVFS_D_COUNT]; // GHz->V
+
+ QuadraticInt_t qStaticVoltageOffset[AVFS_D_COUNT]; // GHz->V
+
+ AvfsDcBtcParams_t DcBtcSocParams[AVFS_D_COUNT];
+
+ uint32_t SocAvfsSpare[32];
+
+ //SECTION: Boot clock and voltage values
+ BootValues_t BootValues;
+
+ //SECTION: Driver Reported Clocks
+ DriverReportedClocks_t DriverReportedClocks;
+
+ //SECTION: Message Limits
+ MsgLimits_t MsgLimits;
+
+ //SECTION: OverDrive Limits
+ OverDriveLimits_t OverDriveLimitsMin;
+ OverDriveLimits_t OverDriveLimitsBasicMax;
+ OverDriveLimits_t OverDriveLimitsAdvancedMax;
+
+ // SECTION: Advanced Options
+ uint32_t DebugOverrides;
+
+ // SECTION: Sku Reserved
+ uint32_t Spare[64];
+
+ // Padding for MMHUB - do not modify this
+ uint32_t MmHubPadding[8];
+
+} SkuTable_t;
+
+typedef struct {
+ // SECTION: Version
+ uint32_t Version; //should be unique to each board type
+
+
+ // SECTION: I2C Control
+ I2cControllerConfig_t I2cControllers[NUM_I2C_CONTROLLERS];
+
+ // SECTION: SVI2 Board Parameters
+ uint8_t VddGfxVrMapping; // Use VR_MAPPING* bitfields
+ uint8_t VddSocVrMapping; // Use VR_MAPPING* bitfields
+ uint8_t VddMem0VrMapping; // Use VR_MAPPING* bitfields
+ uint8_t VddMem1VrMapping; // Use VR_MAPPING* bitfields
+
+ uint8_t GfxUlvPhaseSheddingMask; // set this to 1 to set PSI0/1 to 1 in ULV mode
+ uint8_t SocUlvPhaseSheddingMask; // set this to 1 to set PSI0/1 to 1 in ULV mode
+ uint8_t VmempUlvPhaseSheddingMask; // set this to 1 to set PSI0/1 to 1 in ULV mode
+ uint8_t VddioUlvPhaseSheddingMask; // set this to 1 to set PSI0/1 to 1 in ULV mode
+
+ //SECTION SVI3 Board Parameters
+ uint8_t SlaveAddrMapping[SVI_PLANE_COUNT];
+ uint8_t VrPsiSupport[SVI_PLANE_COUNT];
+
+ uint8_t PaddingPsi[SVI_PLANE_COUNT];
+ uint8_t EnablePsi6[SVI_PLANE_COUNT]; // only applicable in SVI3
+
+ // SECTION: Voltage Regulator Settings
+ SviTelemetryScale_t SviTelemetryScale[SVI_PLANE_COUNT];
+ uint32_t VoltageTelemetryRatio[SVI_PLANE_COUNT]; // This is used for VDDIO Svi2 Div Ratio workaround. It has 16 fractional bits (Q16.16)
+
+ uint8_t DownSlewRateVr[SVI_PLANE_COUNT];
+
+ // SECTION: GPIO Settings
+
+ uint8_t LedOffGpio;
+ uint8_t FanOffGpio;
+ uint8_t GfxVrPowerStageOffGpio;
+
+ uint8_t AcDcGpio; // GPIO pin configured for AC/DC switching
+ uint8_t AcDcPolarity; // GPIO polarity for AC/DC switching
+ uint8_t VR0HotGpio; // GPIO pin configured for VR0 HOT event
+ uint8_t VR0HotPolarity; // GPIO polarity for VR0 HOT event
+
+ uint8_t GthrGpio; // GPIO pin configured for GTHR Event
+ uint8_t GthrPolarity; // replace GPIO polarity for GTHR
+
+ // LED Display Settings
+ uint8_t LedPin0; // GPIO number for LedPin[0]
+ uint8_t LedPin1; // GPIO number for LedPin[1]
+ uint8_t LedPin2; // GPIO number for LedPin[2]
+ uint8_t LedEnableMask;
+
+ uint8_t LedPcie; // GPIO number for PCIE results
+ uint8_t LedError; // GPIO number for Error Cases
+
+ // SECTION: Clock Spread Spectrum
+
+ // UCLK Spread Spectrum
+ uint16_t UclkSpreadPadding;
+ uint16_t UclkSpreadFreq; // kHz
+
+ // UCLK Spread Spectrum
+ uint8_t UclkSpreadPercent[MEM_VENDOR_COUNT];
+
+ // FCLK Spread Spectrum
+ uint8_t FclkSpreadPadding;
+ uint8_t FclkSpreadPercent; // Q4.4
+ uint16_t FclkSpreadFreq; // kHz
+
+ // Section: Memory Config
+ uint8_t DramWidth; // Width of interface to the channel for each DRAM module. See DRAM_BIT_WIDTH_TYPE_e
+ uint8_t PaddingMem1[3];
+
+ // Section: Total Board Power
+ uint16_t TotalBoardPower; //Only needed for TCP Estimated case, where TCP = TGP+Total Board Power
+ uint16_t BoardPowerPadding;
+
+ // SECTION: UMC feature flags
+ uint8_t HsrEnabled;
+ uint8_t VddqOffEnabled;
+ uint8_t PaddingUmcFlags[2];
+
+ uint32_t PostVoltageSetBacoDelay; // in microseconds. Amount of time FW will wait after power good is established or PSI0 command is issued
+ uint32_t BacoEntryDelay; // in milliseconds. Amount of time FW will wait to trigger BACO entry after receiving entry notification from OS
+
+
+ // SECTION: Board Reserved
+ uint32_t BoardSpare[64];
+
+ // SECTION: Structure Padding
+
+ // Padding for MMHUB - do not modify this
+ uint32_t MmHubPadding[8];
+} BoardTable_t;
+
+typedef struct {
+ SkuTable_t SkuTable;
+ BoardTable_t BoardTable;
+} PPTable_t;
+
+typedef struct {
+ // Time constant parameters for clock averages in ms
+ uint16_t GfxclkAverageLpfTau;
+ uint16_t FclkAverageLpfTau;
+ uint16_t UclkAverageLpfTau;
+ uint16_t GfxActivityLpfTau;
+ uint16_t UclkActivityLpfTau;
+ uint16_t SocketPowerLpfTau;
+ uint16_t VcnClkAverageLpfTau;
+ uint16_t VcnUsageAverageLpfTau;
+} DriverSmuConfig_t;
+
+typedef struct {
+ DriverSmuConfig_t DriverSmuConfig;
+
+ uint32_t Spare[8];
+ // Padding - ignore
+ uint32_t MmHubPadding[8]; // SMU internal use
+} DriverSmuConfigExternal_t;
+
+
+typedef struct {
+
+ uint16_t FreqTableGfx [NUM_GFXCLK_DPM_LEVELS ]; // In MHz
+ uint16_t FreqTableVclk [NUM_VCLK_DPM_LEVELS ]; // In MHz
+ uint16_t FreqTableDclk [NUM_DCLK_DPM_LEVELS ]; // In MHz
+ uint16_t FreqTableSocclk [NUM_SOCCLK_DPM_LEVELS ]; // In MHz
+ uint16_t FreqTableUclk [NUM_UCLK_DPM_LEVELS ]; // In MHz
+ uint16_t FreqTableDispclk [NUM_DISPCLK_DPM_LEVELS ]; // In MHz
+ uint16_t FreqTableDppClk [NUM_DPPCLK_DPM_LEVELS ]; // In MHz
+ uint16_t FreqTableDprefclk [NUM_DPREFCLK_DPM_LEVELS]; // In MHz
+ uint16_t FreqTableDcfclk [NUM_DCFCLK_DPM_LEVELS ]; // In MHz
+ uint16_t FreqTableDtbclk [NUM_DTBCLK_DPM_LEVELS ]; // In MHz
+ uint16_t FreqTableFclk [NUM_FCLK_DPM_LEVELS ]; // In MHz
+
+ uint16_t DcModeMaxFreq [PPCLK_COUNT ]; // In MHz
+
+ uint16_t Padding;
+
+ uint32_t Spare[32];
+
+ // Padding - ignore
+ uint32_t MmHubPadding[8]; // SMU internal use
+
+} DriverInfoTable_t;
+
+typedef struct {
+ uint32_t CurrClock[PPCLK_COUNT];
+
+ uint16_t AverageGfxclkFrequencyTarget;
+ uint16_t AverageGfxclkFrequencyPreDs;
+ uint16_t AverageGfxclkFrequencyPostDs;
+ uint16_t AverageFclkFrequencyPreDs;
+ uint16_t AverageFclkFrequencyPostDs;
+ uint16_t AverageMemclkFrequencyPreDs ; // this is scaled to actual memory clock
+ uint16_t AverageMemclkFrequencyPostDs ; // this is scaled to actual memory clock
+ uint16_t AverageVclk0Frequency ;
+ uint16_t AverageDclk0Frequency ;
+ uint16_t AverageVclk1Frequency ;
+ uint16_t AverageDclk1Frequency ;
+
+ uint16_t AvgVoltage[SVI_PLANE_COUNT];
+
+ uint16_t AverageGfxActivity ;
+ uint16_t AverageUclkActivity ;
+ uint16_t Vcn0ActivityPercentage ;
+ uint16_t Vcn1ActivityPercentage ;
+
+ uint32_t EnergyAccumulator;
+ uint16_t AverageSocketPower ;
+ uint16_t AvgTemperature[TEMP_COUNT];
+
+ uint8_t PcieRate ;
+ uint8_t PcieWidth ;
+
+ uint8_t AvgFanPwm;
+ uint8_t Padding[1];
+ uint16_t AvgFanRpm;
+
+
+ uint8_t ThrottlingPercentage[THROTTLER_COUNT];
+
+ //metrics for D3hot entry/exit and driver ARM msgs
+ uint32_t D3HotEntryCountPerMode[D3HOT_SEQUENCE_COUNT];
+ uint32_t D3HotExitCountPerMode[D3HOT_SEQUENCE_COUNT];
+ uint32_t ArmMsgReceivedCountPerMode[D3HOT_SEQUENCE_COUNT];
+
+ uint16_t ApuSTAPMSmartShiftLimit;
+ uint16_t ApuSTAPMLimit;
+ uint16_t AvgApuSocketPower;
+
+ uint16_t AverageUclkActivity_MAX;
+
+} SmuMetrics_t;
+
+typedef struct {
+ SmuMetrics_t SmuMetrics;
+ uint32_t Spare[32];
+
+ // Padding - ignore
+ uint32_t MmHubPadding[8]; // SMU internal use
+} SmuMetricsExternal_t;
+
+typedef struct {
+ uint8_t WmSetting;
+ uint8_t Flags;
+ uint8_t Padding[2];
+
+} WatermarkRowGeneric_t;
+
+#define NUM_WM_RANGES 4
+
+typedef enum {
+ WATERMARKS_CLOCK_RANGE = 0,
+ WATERMARKS_DUMMY_PSTATE,
+ WATERMARKS_MALL,
+ WATERMARKS_COUNT,
+} WATERMARKS_FLAGS_e;
+
+typedef struct {
+ // Watermarks
+ WatermarkRowGeneric_t WatermarkRow[NUM_WM_RANGES];
+} Watermarks_t;
+
+typedef struct {
+ Watermarks_t Watermarks;
+ uint32_t Spare[16];
+
+ uint32_t MmHubPadding[8]; // SMU internal use
+} WatermarksExternal_t;
+
+typedef struct {
+ uint16_t avgPsmCount[36];
+ uint16_t minPsmCount[36];
+ float avgPsmVoltage[36];
+ float minPsmVoltage[36];
+} AvfsDebugTable_t;
+
+typedef struct {
+ AvfsDebugTable_t AvfsDebugTable;
+
+ uint32_t MmHubPadding[8]; // SMU internal use
+} AvfsDebugTableExternal_t;
+
+
+typedef struct {
+ uint8_t Gfx_ActiveHystLimit;
+ uint8_t Gfx_IdleHystLimit;
+ uint8_t Gfx_FPS;
+ uint8_t Gfx_MinActiveFreqType;
+ uint8_t Gfx_BoosterFreqType;
+ uint8_t PaddingGfx;
+ uint16_t Gfx_MinActiveFreq; // MHz
+ uint16_t Gfx_BoosterFreq; // MHz
+ uint16_t Gfx_PD_Data_time_constant; // Time constant of PD controller in ms
+ uint32_t Gfx_PD_Data_limit_a; // Q16
+ uint32_t Gfx_PD_Data_limit_b; // Q16
+ uint32_t Gfx_PD_Data_limit_c; // Q16
+ uint32_t Gfx_PD_Data_error_coeff; // Q16
+ uint32_t Gfx_PD_Data_error_rate_coeff; // Q16
+
+ uint8_t Fclk_ActiveHystLimit;
+ uint8_t Fclk_IdleHystLimit;
+ uint8_t Fclk_FPS;
+ uint8_t Fclk_MinActiveFreqType;
+ uint8_t Fclk_BoosterFreqType;
+ uint8_t PaddingFclk;
+ uint16_t Fclk_MinActiveFreq; // MHz
+ uint16_t Fclk_BoosterFreq; // MHz
+ uint16_t Fclk_PD_Data_time_constant; // Time constant of PD controller in ms
+ uint32_t Fclk_PD_Data_limit_a; // Q16
+ uint32_t Fclk_PD_Data_limit_b; // Q16
+ uint32_t Fclk_PD_Data_limit_c; // Q16
+ uint32_t Fclk_PD_Data_error_coeff; // Q16
+ uint32_t Fclk_PD_Data_error_rate_coeff; // Q16
+
+ uint32_t Mem_UpThreshold_Limit[NUM_UCLK_DPM_LEVELS]; // Q16
+ uint8_t Mem_UpHystLimit[NUM_UCLK_DPM_LEVELS];
+ uint8_t Mem_DownHystLimit[NUM_UCLK_DPM_LEVELS];
+ uint16_t Mem_Fps;
+ uint8_t padding[2];
+
+} DpmActivityMonitorCoeffInt_t;
+
+
+typedef struct {
+ DpmActivityMonitorCoeffInt_t DpmActivityMonitorCoeffInt;
+ uint32_t MmHubPadding[8]; // SMU internal use
+} DpmActivityMonitorCoeffIntExternal_t;
+
+
+
+// Workload bits
+#define WORKLOAD_PPLIB_DEFAULT_BIT 0
+#define WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT 1
+#define WORKLOAD_PPLIB_POWER_SAVING_BIT 2
+#define WORKLOAD_PPLIB_VIDEO_BIT 3
+#define WORKLOAD_PPLIB_VR_BIT 4
+#define WORKLOAD_PPLIB_COMPUTE_BIT 5
+#define WORKLOAD_PPLIB_CUSTOM_BIT 6
+#define WORKLOAD_PPLIB_WINDOW_3D_BIT 7
+#define WORKLOAD_PPLIB_COUNT 8
+
+
+// These defines are used with the following messages:
+// SMC_MSG_TransferTableDram2Smu
+// SMC_MSG_TransferTableSmu2Dram
+
+// Table transfer status
+#define TABLE_TRANSFER_OK 0x0
+#define TABLE_TRANSFER_FAILED 0xFF
+#define TABLE_TRANSFER_PENDING 0xAB
+
+// Table types
+#define TABLE_PPTABLE 0
+#define TABLE_COMBO_PPTABLE 1
+#define TABLE_WATERMARKS 2
+#define TABLE_AVFS_PSM_DEBUG 3
+#define TABLE_PMSTATUSLOG 4
+#define TABLE_SMU_METRICS 5
+#define TABLE_DRIVER_SMU_CONFIG 6
+#define TABLE_ACTIVITY_MONITOR_COEFF 7
+#define TABLE_OVERDRIVE 8
+#define TABLE_I2C_COMMANDS 9
+#define TABLE_DRIVER_INFO 10
+#define TABLE_ECCINFO 11
+#define TABLE_COUNT 12
+
+//IH Interupt ID
+#define IH_INTERRUPT_ID_TO_DRIVER 0xFE
+#define IH_INTERRUPT_CONTEXT_ID_BACO 0x2
+#define IH_INTERRUPT_CONTEXT_ID_AC 0x3
+#define IH_INTERRUPT_CONTEXT_ID_DC 0x4
+#define IH_INTERRUPT_CONTEXT_ID_AUDIO_D0 0x5
+#define IH_INTERRUPT_CONTEXT_ID_AUDIO_D3 0x6
+#define IH_INTERRUPT_CONTEXT_ID_THERMAL_THROTTLING 0x7
+
+#endif
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_0_ppsmc.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_0_ppsmc.h
new file mode 100644
index 000000000000..9ebb8f39732a
--- /dev/null
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_0_ppsmc.h
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2021 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef SMU_V13_0_0_PPSMC_H
+#define SMU_V13_0_0_PPSMC_H
+
+#define PPSMC_VERSION 0x1
+#define DEBUGSMC_VERSION 0x1
+
+// SMU Response Codes:
+#define PPSMC_Result_OK 0x1
+#define PPSMC_Result_Failed 0xFF
+#define PPSMC_Result_UnknownCmd 0xFE
+#define PPSMC_Result_CmdRejectedPrereq 0xFD
+#define PPSMC_Result_CmdRejectedBusy 0xFC
+
+// Message Definitions:
+// BASIC
+#define PPSMC_MSG_TestMessage 0x1
+#define PPSMC_MSG_GetSmuVersion 0x2
+#define PPSMC_MSG_GetDriverIfVersion 0x3
+#define PPSMC_MSG_SetAllowedFeaturesMaskLow 0x4
+#define PPSMC_MSG_SetAllowedFeaturesMaskHigh 0x5
+#define PPSMC_MSG_EnableAllSmuFeatures 0x6
+#define PPSMC_MSG_DisableAllSmuFeatures 0x7
+#define PPSMC_MSG_EnableSmuFeaturesLow 0x8
+#define PPSMC_MSG_EnableSmuFeaturesHigh 0x9
+#define PPSMC_MSG_DisableSmuFeaturesLow 0xA
+#define PPSMC_MSG_DisableSmuFeaturesHigh 0xB
+#define PPSMC_MSG_GetRunningSmuFeaturesLow 0xC
+#define PPSMC_MSG_GetRunningSmuFeaturesHigh 0xD
+#define PPSMC_MSG_SetDriverDramAddrHigh 0xE
+#define PPSMC_MSG_SetDriverDramAddrLow 0xF
+#define PPSMC_MSG_SetToolsDramAddrHigh 0x10
+#define PPSMC_MSG_SetToolsDramAddrLow 0x11
+#define PPSMC_MSG_TransferTableSmu2Dram 0x12
+#define PPSMC_MSG_TransferTableDram2Smu 0x13
+#define PPSMC_MSG_UseDefaultPPTable 0x14
+
+//BACO/BAMACO/BOMACO
+#define PPSMC_MSG_EnterBaco 0x15
+#define PPSMC_MSG_ExitBaco 0x16
+#define PPSMC_MSG_ArmD3 0x17
+#define PPSMC_MSG_BacoAudioD3PME 0x18
+
+//DPM
+#define PPSMC_MSG_SetSoftMinByFreq 0x19
+#define PPSMC_MSG_SetSoftMaxByFreq 0x1A
+#define PPSMC_MSG_SetHardMinByFreq 0x1B
+#define PPSMC_MSG_SetHardMaxByFreq 0x1C
+#define PPSMC_MSG_GetMinDpmFreq 0x1D
+#define PPSMC_MSG_GetMaxDpmFreq 0x1E
+#define PPSMC_MSG_GetDpmFreqByIndex 0x1F
+#define PPSMC_MSG_OverridePcieParameters 0x20
+
+//DramLog Set DramAddr
+#define PPSMC_MSG_DramLogSetDramAddrHigh 0x21
+#define PPSMC_MSG_DramLogSetDramAddrLow 0x22
+#define PPSMC_MSG_DramLogSetDramSize 0x23
+#define PPSMC_MSG_SetWorkloadMask 0x24
+
+#define PPSMC_MSG_GetVoltageByDpm 0x25
+#define PPSMC_MSG_SetVideoFps 0x26
+#define PPSMC_MSG_GetDcModeMaxDpmFreq 0x27
+
+//Power Gating
+#define PPSMC_MSG_AllowGfxOff 0x28
+#define PPSMC_MSG_DisallowGfxOff 0x29
+#define PPSMC_MSG_PowerUpVcn 0x2A
+#define PPSMC_MSG_PowerDownVcn 0x2B
+#define PPSMC_MSG_PowerUpJpeg 0x2C
+#define PPSMC_MSG_PowerDownJpeg 0x2D
+
+//Resets
+#define PPSMC_MSG_PrepareMp1ForUnload 0x2E
+#define PPSMC_MSG_Mode1Reset 0x2F
+
+//Set SystemVirtual DramAddrHigh
+#define PPSMC_MSG_SetSystemVirtualDramAddrHigh 0x30
+#define PPSMC_MSG_SetSystemVirtualDramAddrLow 0x31
+//ACDC Power Source
+#define PPSMC_MSG_SetPptLimit 0x32
+#define PPSMC_MSG_GetPptLimit 0x33
+#define PPSMC_MSG_ReenableAcDcInterrupt 0x34
+#define PPSMC_MSG_NotifyPowerSource 0x35
+
+//BTC
+#define PPSMC_MSG_RunDcBtc 0x36
+
+//Debug
+#define PPSMC_MSG_GetDebugData 0x37
+
+//Others
+#define PPSMC_MSG_SetTemperatureInputSelect 0x38
+#define PPSMC_MSG_SetFwDstatesMask 0x39
+#define PPSMC_MSG_SetThrottlerMask 0x3A
+
+#define PPSMC_MSG_SetExternalClientDfCstateAllow 0x3B
+
+#define PPSMC_MSG_SetMGpuFanBoostLimitRpm 0x3C
+
+//STB to dram log
+#define PPSMC_MSG_DumpSTBtoDram 0x3D
+#define PPSMC_MSG_STBtoDramLogSetDramAddrHigh 0x3E
+#define PPSMC_MSG_STBtoDramLogSetDramAddrLow 0x3F
+#define PPSMC_MSG_STBtoDramLogSetDramSize 0x40
+
+#define PPSMC_MSG_SetGpoAllow 0x41
+#define PPSMC_MSG_AllowGfxDcs 0x42
+#define PPSMC_MSG_DisallowGfxDcs 0x43
+#define PPSMC_MSG_EnableAudioStutterWA 0x44
+#define PPSMC_MSG_PowerUpUmsch 0x45
+#define PPSMC_MSG_PowerDownUmsch 0x46
+#define PPSMC_Message_Count 0x47
+
+//Debug Dump Message
+#define DEBUGSMC_MSG_TestMessage 0x1
+#define DEBUGSMC_MSG_GetDebugData 0x2
+#define DEBUGSMC_MSG_DebugDumpExit 0x3
+#define DEBUGSMC_Message_Count 0x4
+#endif
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_4_pmfw.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_4_pmfw.h
new file mode 100644
index 000000000000..8f37efc3db6c
--- /dev/null
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_4_pmfw.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2022 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __SMU_V13_0_4_PMFW_H__
+#define __SMU_V13_0_4_PMFW_H__
+
+#include "smu13_driver_if_v13_0_4.h"
+
+#pragma pack(push, 1)
+
+#define ENABLE_DEBUG_FEATURES
+
+// Firmware features
+// Feature Control Defines
+#define FEATURE_CCLK_DPM_BIT 0
+#define FEATURE_FAN_CONTROLLER_BIT 1
+#define FEATURE_DATA_CALCULATION_BIT 2
+#define FEATURE_PPT_BIT 3
+#define FEATURE_TDC_BIT 4
+#define FEATURE_THERMAL_BIT 5
+#define FEATURE_FIT_BIT 6
+#define FEATURE_EDC_BIT 7
+#define FEATURE_PLL_POWER_DOWN_BIT 8
+#define FEATURE_VDDOFF_BIT 9
+#define FEATURE_VCN_DPM_BIT 10
+#define FEATURE_CSTATE_BOOST_BIT 11
+#define FEATURE_FCLK_DPM_BIT 12
+#define FEATURE_SOCCLK_DPM_BIT 13
+#define FEATURE_MP0CLK_DPM_BIT 14
+#define FEATURE_LCLK_DPM_BIT 15
+#define FEATURE_SHUBCLK_DPM_BIT 16
+#define FEATURE_DCFCLK_DPM_BIT 17
+#define FEATURE_ISP_DPM_BIT 18
+#define FEATURE_IPU_DPM_BIT 19
+#define FEATURE_GFX_DPM_BIT 20
+#define FEATURE_DS_GFXCLK_BIT 21
+#define FEATURE_DS_SOCCLK_BIT 22
+#define FEATURE_DS_LCLK_BIT 23
+#define FEATURE_DS_DCFCLK_BIT 24
+#define FEATURE_DS_SHUBCLK_BIT 25
+#define FEATURE_GFX_TEMP_VMIN_BIT 26
+#define FEATURE_ZSTATES_BIT 27
+#define FEATURE_WHISPER_MODE_BIT 28
+#define FEATURE_DS_FCLK_BIT 29
+#define FEATURE_DS_SMNCLK_BIT 30
+#define FEATURE_DS_MP1CLK_BIT 31
+#define FEATURE_DS_MP0CLK_BIT 32
+#define FEATURE_SMU_LOW_POWER_BIT 33
+#define FEATURE_FUSE_PG_BIT 34
+#define FEATURE_GFX_DEM_BIT 35
+#define FEATURE_PSI_BIT 36
+#define FEATURE_PROCHOT_BIT 37
+#define FEATURE_CPUOFF_BIT 38
+#define FEATURE_STAPM_BIT 39
+#define FEATURE_S0I3_BIT 40
+#define FEATURE_DF_LIGHT_CSTATE 41 // shift the order or DFCstate annd DF light Cstate
+#define FEATURE_PERF_LIMIT_BIT 42
+#define FEATURE_CORE_DLDO_BIT 43
+//#define FEATURE_RSMU_LOW_POWER_BIT 44 //temp removal for DVO
+#define FEATURE_DVO_BIT 44
+#define FEATURE_DS_VCN_BIT 45
+#define FEATURE_CPPC_BIT 46
+#define FEATURE_CPPC_PREFERRED_CORES 47
+#define FEATURE_DF_CSTATES_BIT 48
+#define FEATURE_FASTBYPASS_CLDO_BIT 49
+#define FEATURE_ATHUB_PG_BIT 50
+#define FEATURE_VDDOFF_ECO_BIT 51
+#define FEATURE_ZSTATES_ECO_BIT 52
+#define FEATURE_CC6_BIT 53
+#define FEATURE_DS_UMCCLK_BIT 54
+#define FEATURE_DS_ISPCLK_BIT 55
+#define FEATURE_DS_HSPCLK_BIT 56
+#define FEATURE_MPCCX_WHISPER_MODE_BIT 57
+#define FEATURE_DS_IPUCLK_BIT 58
+#define NUM_FEATURES 59
+
+typedef struct {
+ // MP1_EXT_SCRATCH0
+ uint32_t DpmHandlerID : 8;
+ uint32_t ActivityMonitorID : 8;
+ uint32_t DpmTimerID : 8;
+ uint32_t DpmHubID : 4;
+ uint32_t DpmHubTask : 4;
+ // MP1_EXT_SCRATCH1
+ uint32_t GfxoffStatus : 8;
+ uint32_t GfxStatus : 2;
+ uint32_t CpuOff : 2;
+ uint32_t VddOff : 1;
+ uint32_t InUlv : 1;
+ uint32_t InWhisperMode : 1;
+ uint32_t spare0 : 1;
+ uint32_t ZstateStatus : 4;
+ uint32_t spare1 : 4;
+ uint32_t DstateFun : 4;
+ uint32_t DstateDev : 4;
+ // MP1_EXT_SCRATCH2
+ uint32_t P2JobHandler :32;
+ // MP1_EXT_SCRATCH3
+ uint32_t PostCode :32;
+ // MP1_EXT_SCRATCH4
+ uint32_t MsgPortBusy :15;
+ uint32_t RsmuPmiP1Pending : 1;
+ uint32_t RsmuPmiP2PendingCnt : 8;
+ uint32_t DfCstateExitPending : 1;
+ uint32_t Pc6EntryPending : 1;
+ uint32_t Pc6ExitPending : 1;
+ uint32_t WarmResetPending : 1;
+ uint32_t Mp0ClkPending : 1;
+ uint32_t spare2 : 3;
+ // MP1_EXT_SCRATCH5
+ uint32_t IdleMask :32;
+} FwStatus_t;
+
+
+#pragma pack(pop)
+
+#endif
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_4_ppsmc.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_4_ppsmc.h
new file mode 100644
index 000000000000..d9b0cd752200
--- /dev/null
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_4_ppsmc.h
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2022 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __SMU_V13_0_4_PPSMC_H__
+#define __SMU_V13_0_4_PPSMC_H__
+
+/*! @mainpage PMFW-PPS (PPLib) Message Interface
+ This documentation contains the subsections:\n\n
+ @ref ResponseCodes\n
+ @ref definitions\n
+ @ref enums\n
+*/
+
+/** @def PPS_PMFW_IF_VER
+* PPS (PPLib) to PMFW IF version 1.0
+*/
+#define PPS_PMFW_IF_VER "1.0" ///< Major.Minor
+
+/** @defgroup ResponseCodes PMFW Response Codes
+* @{
+*/
+// SMU Response Codes:
+#define PPSMC_Result_OK 0x1 ///< Message Response OK
+#define PPSMC_Result_Failed 0xFF ///< Message Response Failed
+#define PPSMC_Result_UnknownCmd 0xFE ///< Message Response Unknown Command
+#define PPSMC_Result_CmdRejectedPrereq 0xFD ///< Message Response Command Failed Prerequisite
+#define PPSMC_Result_CmdRejectedBusy 0xFC ///< Message Response Command Rejected due to PMFW is busy. Sender should retry sending this message
+/** @}*/
+
+/** @defgroup definitions Message definitions
+* @{
+*/
+// Message Definitions:
+#define PPSMC_MSG_TestMessage 0x01 ///< To check if PMFW is alive and responding. Requirement specified by PMFW team
+#define PPSMC_MSG_GetPmfwVersion 0x02 ///< Get PMFW version
+#define PPSMC_MSG_GetDriverIfVersion 0x03 ///< Get PMFW_DRIVER_IF version
+#define PPSMC_MSG_EnableGfxOff 0x04 ///< Enable GFXOFF
+#define PPSMC_MSG_DisableGfxOff 0x05 ///< Disable GFXOFF
+#define PPSMC_MSG_PowerDownVcn 0x06 ///< Power down VCN
+#define PPSMC_MSG_PowerUpVcn 0x07 ///< Power up VCN; VCN is power gated by default
+#define PPSMC_MSG_SetHardMinVcn 0x08 ///< For wireless display
+#define PPSMC_MSG_SetSoftMinGfxclk 0x09 ///< Set SoftMin for GFXCLK, argument is frequency in MHz
+#define PPSMC_MSG_ActiveProcessNotify 0x0A ///< Needs update
+#define PPSMC_MSG_ForcePowerDownGfx 0x0B ///< Force power down GFX, i.e. enter GFXOFF
+#define PPSMC_MSG_PrepareMp1ForUnload 0x0C ///< Prepare PMFW for GFX driver unload
+#define PPSMC_MSG_SetDriverDramAddrHigh 0x0D ///< Set high 32 bits of DRAM address for Driver table transfer
+#define PPSMC_MSG_SetDriverDramAddrLow 0x0E ///< Set low 32 bits of DRAM address for Driver table transfer
+#define PPSMC_MSG_TransferTableSmu2Dram 0x0F ///< Transfer driver interface table from PMFW SRAM to DRAM
+#define PPSMC_MSG_TransferTableDram2Smu 0x10 ///< Transfer driver interface table from DRAM to PMFW SRAM
+#define PPSMC_MSG_GfxDeviceDriverReset 0x11 ///< Request GFX mode 2 reset
+#define PPSMC_MSG_GetEnabledSmuFeatures 0x12 ///< Get enabled features in PMFW
+#define PPSMC_MSG_SetHardMinSocclkByFreq 0x13 ///< Set hard min for SOC CLK
+#define PPSMC_MSG_SetSoftMinFclk 0x14 ///< Set hard min for FCLK
+#define PPSMC_MSG_SetSoftMinVcn 0x15 ///< Set soft min for VCN clocks (VCLK and DCLK)
+
+
+#define PPSMC_MSG_EnableGfxImu 0x16 ///< Needs update
+
+#define PPSMC_MSG_GetGfxclkFrequency 0x17 ///< Get GFX clock frequency
+#define PPSMC_MSG_GetFclkFrequency 0x18 ///< Get FCLK frequency
+#define PPSMC_MSG_AllowGfxOff 0x19 ///< Inform PMFW of allowing GFXOFF entry
+#define PPSMC_MSG_DisallowGfxOff 0x1A ///< Inform PMFW of disallowing GFXOFF entry
+#define PPSMC_MSG_SetSoftMaxGfxClk 0x1B ///< Set soft max for GFX CLK
+#define PPSMC_MSG_SetHardMinGfxClk 0x1C ///< Set hard min for GFX CLK
+
+#define PPSMC_MSG_SetSoftMaxSocclkByFreq 0x1D ///< Set soft max for SOC CLK
+#define PPSMC_MSG_SetSoftMaxFclkByFreq 0x1E ///< Set soft max for FCLK
+#define PPSMC_MSG_SetSoftMaxVcn 0x1F ///< Set soft max for VCN clocks (VCLK and DCLK)
+#define PPSMC_MSG_SetPowerLimitPercentage 0x20 ///< Set power limit percentage
+#define PPSMC_MSG_PowerDownJpeg 0x21 ///< Power down Jpeg
+#define PPSMC_MSG_PowerUpJpeg 0x22 ///< Power up Jpeg; VCN is power gated by default
+
+#define PPSMC_MSG_SetHardMinFclkByFreq 0x23 ///< Set hard min for FCLK
+#define PPSMC_MSG_SetSoftMinSocclkByFreq 0x24 ///< Set soft min for SOC CLK
+#define PPSMC_MSG_AllowZstates 0x25 ///< Inform PMFM of allowing Zstate entry, i.e. no Miracast activity
+#define PPSMC_MSG_Reserved 0x26 ///< Not used
+#define PPSMC_MSG_Reserved1 0x27 ///< Not used, previously PPSMC_MSG_RequestActiveWgp
+#define PPSMC_MSG_Reserved2 0x28 ///< Not used, previously PPSMC_MSG_QueryActiveWgp
+#define PPSMC_MSG_PowerDownIspByTile 0x29 ///< ISP is power gated by default
+#define PPSMC_MSG_PowerUpIspByTile 0x2A ///< This message is used to power up ISP tiles and enable the ISP DPM
+#define PPSMC_MSG_SetHardMinIspiclkByFreq 0x2B ///< Set HardMin by frequency for ISPICLK
+#define PPSMC_MSG_SetHardMinIspxclkByFreq 0x2C ///< Set HardMin by frequency for ISPXCLK
+#define PPSMC_MSG_PowerDownUmsch 0x2D ///< Power down VCN.UMSCH (aka VSCH) scheduler
+#define PPSMC_MSG_PowerUpUmsch 0x2E ///< Power up VCN.UMSCH (aka VSCH) scheduler
+#define PPSMC_Message_IspStutterOn_MmhubPgDis 0x2F ///< ISP StutterOn mmHub PgDis
+#define PPSMC_Message_IspStutterOff_MmhubPgEn 0x30 ///< ISP StufferOff mmHub PgEn
+
+#define PPSMC_Message_Count 0x31 ///< Total number of PPSMC messages
+/** @}*/
+
+/**
+* @defgroup enums Enum Definitions
+* @{
+*/
+
+/** @enum Mode_Reset_e
+* Mode reset type, argument for PPSMC_MSG_GfxDeviceDriverReset
+*/
+//argument for PPSMC_MSG_GfxDeviceDriverReset
+typedef enum {
+ MODE1_RESET = 1, ///< Mode reset type 1
+ MODE2_RESET = 2 ///< Mode reset type 2
+} Mode_Reset_e;
+
+/** @}*/
+
+/** @enum ZStates_e
+* Zstate types, argument for PPSMC_MSG_AllowZstates
+*/
+//Argument for PPSMC_MSG_AllowZstates
+typedef enum {
+ DISALLOW_ZSTATES = 0, ///< Disallow Zstates
+ ALLOW_ZSTATES_Z8 = 8, ///< Allows Z8 only
+ ALLOW_ZSTATES_Z9 = 9, ///< Allows Z9 and Z8
+} ZStates_e;
+
+/** @}*/
+#endif
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_7_ppsmc.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_7_ppsmc.h
new file mode 100644
index 000000000000..3f2d0a9e4745
--- /dev/null
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_7_ppsmc.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2021 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+#ifndef SMU_V13_0_7_PPSMC_H
+#define SMU_V13_0_7_PPSMC_H
+
+#define PPSMC_VERSION 0x1
+
+// SMU Response Codes:
+#define PPSMC_Result_OK 0x1
+#define PPSMC_Result_Failed 0xFF
+#define PPSMC_Result_UnknownCmd 0xFE
+#define PPSMC_Result_CmdRejectedPrereq 0xFD
+#define PPSMC_Result_CmdRejectedBusy 0xFC
+
+// Message Definitions:
+// BASIC
+#define PPSMC_MSG_TestMessage 0x1
+#define PPSMC_MSG_GetSmuVersion 0x2
+#define PPSMC_MSG_GetDriverIfVersion 0x3
+#define PPSMC_MSG_SetAllowedFeaturesMaskLow 0x4
+#define PPSMC_MSG_SetAllowedFeaturesMaskHigh 0x5
+#define PPSMC_MSG_EnableAllSmuFeatures 0x6
+#define PPSMC_MSG_DisableAllSmuFeatures 0x7
+#define PPSMC_MSG_EnableSmuFeaturesLow 0x8
+#define PPSMC_MSG_EnableSmuFeaturesHigh 0x9
+#define PPSMC_MSG_DisableSmuFeaturesLow 0xA
+#define PPSMC_MSG_DisableSmuFeaturesHigh 0xB
+#define PPSMC_MSG_GetRunningSmuFeaturesLow 0xC
+#define PPSMC_MSG_GetRunningSmuFeaturesHigh 0xD
+#define PPSMC_MSG_SetDriverDramAddrHigh 0xE
+#define PPSMC_MSG_SetDriverDramAddrLow 0xF
+#define PPSMC_MSG_SetToolsDramAddrHigh 0x10
+#define PPSMC_MSG_SetToolsDramAddrLow 0x11
+#define PPSMC_MSG_TransferTableSmu2Dram 0x12
+#define PPSMC_MSG_TransferTableDram2Smu 0x13
+#define PPSMC_MSG_UseDefaultPPTable 0x14
+
+//BACO/BAMACO/BOMACO
+#define PPSMC_MSG_EnterBaco 0x15
+#define PPSMC_MSG_ExitBaco 0x16
+#define PPSMC_MSG_ArmD3 0x17
+#define PPSMC_MSG_BacoAudioD3PME 0x18
+
+//DPM
+#define PPSMC_MSG_SetSoftMinByFreq 0x19
+#define PPSMC_MSG_SetSoftMaxByFreq 0x1A
+#define PPSMC_MSG_SetHardMinByFreq 0x1B
+#define PPSMC_MSG_SetHardMaxByFreq 0x1C
+#define PPSMC_MSG_GetMinDpmFreq 0x1D
+#define PPSMC_MSG_GetMaxDpmFreq 0x1E
+#define PPSMC_MSG_GetDpmFreqByIndex 0x1F
+#define PPSMC_MSG_OverridePcieParameters 0x20
+
+//DramLog Set DramAddr
+#define PPSMC_MSG_DramLogSetDramAddrHigh 0x21
+#define PPSMC_MSG_DramLogSetDramAddrLow 0x22
+#define PPSMC_MSG_DramLogSetDramSize 0x23
+#define PPSMC_MSG_SetWorkloadMask 0x24
+
+#define PPSMC_MSG_GetVoltageByDpm 0x25
+#define PPSMC_MSG_SetVideoFps 0x26
+#define PPSMC_MSG_GetDcModeMaxDpmFreq 0x27
+
+//Power Gating
+#define PPSMC_MSG_AllowGfxOff 0x28
+#define PPSMC_MSG_DisallowGfxOff 0x29
+#define PPSMC_MSG_PowerUpVcn 0x2A
+#define PPSMC_MSG_PowerDownVcn 0x2B
+#define PPSMC_MSG_PowerUpJpeg 0x2C
+#define PPSMC_MSG_PowerDownJpeg 0x2D
+
+//Resets
+#define PPSMC_MSG_PrepareMp1ForUnload 0x2E
+#define PPSMC_MSG_Mode1Reset 0x2F
+
+//Set SystemVirtual DramAddrHigh
+#define PPSMC_MSG_SetSystemVirtualDramAddrHigh 0x30
+#define PPSMC_MSG_SetSystemVirtualDramAddrLow 0x31
+//ACDC Power Source
+#define PPSMC_MSG_SetPptLimit 0x32
+#define PPSMC_MSG_GetPptLimit 0x33
+#define PPSMC_MSG_ReenableAcDcInterrupt 0x34
+#define PPSMC_MSG_NotifyPowerSource 0x35
+
+//BTC
+#define PPSMC_MSG_RunDcBtc 0x36
+
+// 0x37
+
+//Others
+#define PPSMC_MSG_SetTemperatureInputSelect 0x38
+#define PPSMC_MSG_SetFwDstatesMask 0x39
+#define PPSMC_MSG_SetThrottlerMask 0x3A
+
+#define PPSMC_MSG_SetExternalClientDfCstateAllow 0x3B
+
+#define PPSMC_MSG_SetMGpuFanBoostLimitRpm 0x3C
+
+//STB to dram log
+#define PPSMC_MSG_DumpSTBtoDram 0x3D
+#define PPSMC_MSG_STBtoDramLogSetDramAddrHigh 0x3E
+#define PPSMC_MSG_STBtoDramLogSetDramAddrLow 0x3F
+#define PPSMC_MSG_STBtoDramLogSetDramSize 0x40
+
+#define PPSMC_MSG_SetGpoAllow 0x41
+#define PPSMC_MSG_AllowGfxDcs 0x42
+#define PPSMC_MSG_DisallowGfxDcs 0x43
+#define PPSMC_MSG_EnableAudioStutterWA 0x44
+#define PPSMC_MSG_PowerUpUmsch 0x45
+#define PPSMC_MSG_PowerDownUmsch 0x46
+#define PPSMC_Message_Count 0x4C
+
+
+#endif
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h
index 9f6f306eeca0..a1cb8e73e171 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h
@@ -233,7 +233,8 @@
__SMU_DUMMY_MAP(Spare0), \
__SMU_DUMMY_MAP(UnforceGfxVid), \
__SMU_DUMMY_MAP(HeavySBR), \
- __SMU_DUMMY_MAP(SetBadHBMPagesRetiredFlagsPerChannel),
+ __SMU_DUMMY_MAP(SetBadHBMPagesRetiredFlagsPerChannel), \
+ __SMU_DUMMY_MAP(EnableGfxImu),
#undef __SMU_DUMMY_MAP
#define __SMU_DUMMY_MAP(type) SMU_MSG_##type
@@ -366,6 +367,31 @@ enum smu_clk_type {
__SMU_DUMMY_MAP(THM_CG), \
__SMU_DUMMY_MAP(CLK_CG), \
__SMU_DUMMY_MAP(DATA_CALCULATION), \
+ __SMU_DUMMY_MAP(DPM_VCLK), \
+ __SMU_DUMMY_MAP(DPM_DCLK), \
+ __SMU_DUMMY_MAP(FW_DATA_READ), \
+ __SMU_DUMMY_MAP(DPM_GFX_POWER_OPTIMIZER), \
+ __SMU_DUMMY_MAP(DPM_DCN), \
+ __SMU_DUMMY_MAP(VMEMP_SCALING), \
+ __SMU_DUMMY_MAP(VDDIO_MEM_SCALING), \
+ __SMU_DUMMY_MAP(MM_DPM), \
+ __SMU_DUMMY_MAP(SOC_MPCLK_DS), \
+ __SMU_DUMMY_MAP(BACO_MPCLK_DS), \
+ __SMU_DUMMY_MAP(THROTTLERS), \
+ __SMU_DUMMY_MAP(SMARTSHIFT), \
+ __SMU_DUMMY_MAP(GFX_READ_MARGIN), \
+ __SMU_DUMMY_MAP(GFX_IMU), \
+ __SMU_DUMMY_MAP(GFX_PCC_DFLL), \
+ __SMU_DUMMY_MAP(BOOT_TIME_CAL), \
+ __SMU_DUMMY_MAP(BOOT_POWER_OPT), \
+ __SMU_DUMMY_MAP(GFXCLK_SPREAD_SPECTRUM), \
+ __SMU_DUMMY_MAP(SOC_PCC), \
+ __SMU_DUMMY_MAP(OPTIMIZED_VMIN), \
+ __SMU_DUMMY_MAP(CLOCK_POWER_DOWN_BYPASS), \
+ __SMU_DUMMY_MAP(MEM_TEMP_READ), \
+ __SMU_DUMMY_MAP(ATHUB_MMHUB_PG), \
+ __SMU_DUMMY_MAP(BACO_CG), \
+ __SMU_DUMMY_MAP(SOC_CG),
#undef __SMU_DUMMY_MAP
#define __SMU_DUMMY_MAP(feature) SMU_FEATURE_##feature##_BIT
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h
index d0d5b9b2c65b..2b44d41a5157 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h
@@ -28,9 +28,12 @@
#define SMU13_DRIVER_IF_VERSION_INV 0xFFFFFFFF
#define SMU13_DRIVER_IF_VERSION_YELLOW_CARP 0x04
#define SMU13_DRIVER_IF_VERSION_ALDE 0x08
+#define SMU13_DRIVER_IF_VERSION_SMU_V13_0_4 0x04
+#define SMU13_DRIVER_IF_VERSION_SMU_V13_0_5 0x04
+#define SMU13_DRIVER_IF_VERSION_SMU_V13_0_0 0x27
+#define SMU13_DRIVER_IF_VERSION_SMU_V13_0_7 0x28
#define SMU13_MODE1_RESET_WAIT_TIME_IN_MS 500 //500ms
-#define SMU13_DRIVER_IF_VERSION_SMU_V13_0_5 0x04
/* MP Apertures */
#define MP0_Public 0x03800000
@@ -49,7 +52,7 @@
#define SMU13_TOOL_SIZE 0x19000
#define MAX_DPM_LEVELS 16
-#define MAX_PCIE_CONF 2
+#define MAX_PCIE_CONF 3
#define CTF_OFFSET_EDGE 5
#define CTF_OFFSET_HOTSPOT 5
@@ -73,12 +76,15 @@ struct smu_13_0_dpm_table {
uint32_t min; /* MHz */
uint32_t max; /* MHz */
uint32_t count;
+ bool is_fine_grained;
struct smu_13_0_dpm_clk_level dpm_levels[MAX_DPM_LEVELS];
};
struct smu_13_0_pcie_table {
uint8_t pcie_gen[MAX_PCIE_CONF];
uint8_t pcie_lane[MAX_PCIE_CONF];
+ uint16_t clk_freq[MAX_PCIE_CONF];
+ uint32_t num_of_link_levels;
};
struct smu_13_0_dpm_tables {
@@ -192,8 +198,8 @@ int
smu_v13_0_set_fan_control_mode(struct smu_context *smu,
uint32_t mode);
-int
-smu_v13_0_set_fan_speed_percent(struct smu_context *smu, uint32_t speed);
+int smu_v13_0_set_fan_speed_pwm(struct smu_context *smu,
+ uint32_t speed);
int smu_v13_0_set_fan_speed_rpm(struct smu_context *smu,
uint32_t speed);
@@ -219,8 +225,6 @@ int smu_v13_0_baco_set_state(struct smu_context *smu, enum smu_baco_state state)
int smu_v13_0_baco_enter(struct smu_context *smu);
int smu_v13_0_baco_exit(struct smu_context *smu);
-int smu_v13_0_mode2_reset(struct smu_context *smu);
-
int smu_v13_0_get_dpm_ultimate_freq(struct smu_context *smu, enum smu_clk_type clk_type,
uint32_t *min, uint32_t *max);
@@ -238,15 +242,6 @@ int smu_v13_0_set_performance_level(struct smu_context *smu,
int smu_v13_0_set_power_source(struct smu_context *smu,
enum smu_power_src_type power_src);
-int smu_v13_0_get_dpm_freq_by_index(struct smu_context *smu,
- enum smu_clk_type clk_type,
- uint16_t level,
- uint32_t *value);
-
-int smu_v13_0_get_dpm_level_count(struct smu_context *smu,
- enum smu_clk_type clk_type,
- uint32_t *value);
-
int smu_v13_0_set_single_dpm_table(struct smu_context *smu,
enum smu_clk_type clk_type,
struct smu_13_0_dpm_table *single_dpm_table);
@@ -270,5 +265,38 @@ int smu_v13_0_gfx_ulv_control(struct smu_context *smu,
int smu_v13_0_wait_for_event(struct smu_context *smu, enum smu_event_type event,
uint64_t event_arg);
+int smu_v13_0_set_vcn_enable(struct smu_context *smu,
+ bool enable);
+
+int smu_v13_0_set_jpeg_enable(struct smu_context *smu,
+ bool enable);
+
+int smu_v13_0_init_pptable_microcode(struct smu_context *smu);
+
+int smu_v13_0_run_btc(struct smu_context *smu);
+
+int smu_v13_0_deep_sleep_control(struct smu_context *smu,
+ bool enablement);
+
+int smu_v13_0_gfx_ulv_control(struct smu_context *smu,
+ bool enablement);
+
+bool smu_v13_0_baco_is_support(struct smu_context *smu);
+
+enum smu_baco_state smu_v13_0_baco_get_state(struct smu_context *smu);
+
+int smu_v13_0_baco_set_state(struct smu_context *smu,
+ enum smu_baco_state state);
+
+int smu_v13_0_baco_enter(struct smu_context *smu);
+
+int smu_v13_0_baco_exit(struct smu_context *smu);
+
+int smu_v13_0_od_edit_dpm_table(struct smu_context *smu,
+ enum PP_OD_DPM_TABLE_COMMAND type,
+ long input[],
+ uint32_t size);
+
+int smu_v13_0_set_default_dpm_tables(struct smu_context *smu);
#endif
#endif
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0_7_pptable.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0_7_pptable.h
new file mode 100644
index 000000000000..3f29f4327378
--- /dev/null
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0_7_pptable.h
@@ -0,0 +1,200 @@
+/*
+ * Copyright 2022 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef SMU_13_0_7_PPTABLE_H
+#define SMU_13_0_7_PPTABLE_H
+
+#define SMU_13_0_7_TABLE_FORMAT_REVISION 15
+
+//// POWERPLAYTABLE::ulPlatformCaps
+#define SMU_13_0_7_PP_PLATFORM_CAP_POWERPLAY 0x1 // This cap indicates whether CCC need to show Powerplay page.
+#define SMU_13_0_7_PP_PLATFORM_CAP_SBIOSPOWERSOURCE 0x2 // This cap indicates whether power source notificaiton is done by SBIOS instead of OS.
+#define SMU_13_0_7_PP_PLATFORM_CAP_HARDWAREDC 0x4 // This cap indicates whether DC mode notificaiton is done by GPIO pin directly.
+#define SMU_13_0_7_PP_PLATFORM_CAP_BACO 0x8 // This cap indicates whether board supports the BACO circuitry.
+#define SMU_13_0_7_PP_PLATFORM_CAP_MACO 0x10 // This cap indicates whether board supports the MACO circuitry.
+#define SMU_13_0_7_PP_PLATFORM_CAP_SHADOWPSTATE 0x20 // This cap indicates whether board supports the Shadow Pstate.
+
+// SMU_13_0_7_PP_THERMALCONTROLLER - Thermal Controller Type
+#define SMU_13_0_7_PP_THERMALCONTROLLER_NONE 0
+#define SMU_13_0_7_PP_THERMALCONTROLLER_NAVI21 28
+
+#define SMU_13_0_7_PP_OVERDRIVE_VERSION 0x81 // OverDrive 8 Table Version 0.2
+#define SMU_13_0_7_PP_POWERSAVINGCLOCK_VERSION 0x01 // Power Saving Clock Table Version 1.00
+
+enum SMU_13_0_7_ODFEATURE_CAP
+{
+ SMU_13_0_7_ODCAP_GFXCLK_LIMITS = 0,
+ SMU_13_0_7_ODCAP_GFXCLK_CURVE,
+ SMU_13_0_7_ODCAP_UCLK_LIMITS,
+ SMU_13_0_7_ODCAP_POWER_LIMIT,
+ SMU_13_0_7_ODCAP_FAN_ACOUSTIC_LIMIT,
+ SMU_13_0_7_ODCAP_FAN_SPEED_MIN,
+ SMU_13_0_7_ODCAP_TEMPERATURE_FAN,
+ SMU_13_0_7_ODCAP_TEMPERATURE_SYSTEM,
+ SMU_13_0_7_ODCAP_MEMORY_TIMING_TUNE,
+ SMU_13_0_7_ODCAP_FAN_ZERO_RPM_CONTROL,
+ SMU_13_0_7_ODCAP_AUTO_UV_ENGINE,
+ SMU_13_0_7_ODCAP_AUTO_OC_ENGINE,
+ SMU_13_0_7_ODCAP_AUTO_OC_MEMORY,
+ SMU_13_0_7_ODCAP_FAN_CURVE,
+ SMU_13_0_7_ODCAP_AUTO_FAN_ACOUSTIC_LIMIT,
+ SMU_13_0_7_ODCAP_POWER_MODE,
+ SMU_13_0_7_ODCAP_COUNT,
+};
+
+enum SMU_13_0_7_ODFEATURE_ID
+{
+ SMU_13_0_7_ODFEATURE_GFXCLK_LIMITS = 1 << SMU_13_0_7_ODCAP_GFXCLK_LIMITS, //GFXCLK Limit feature
+ SMU_13_0_7_ODFEATURE_GFXCLK_CURVE = 1 << SMU_13_0_7_ODCAP_GFXCLK_CURVE, //GFXCLK Curve feature
+ SMU_13_0_7_ODFEATURE_UCLK_LIMITS = 1 << SMU_13_0_7_ODCAP_UCLK_LIMITS, //UCLK Limit feature
+ SMU_13_0_7_ODFEATURE_POWER_LIMIT = 1 << SMU_13_0_7_ODCAP_POWER_LIMIT, //Power Limit feature
+ SMU_13_0_7_ODFEATURE_FAN_ACOUSTIC_LIMIT = 1 << SMU_13_0_7_ODCAP_FAN_ACOUSTIC_LIMIT, //Fan Acoustic RPM feature
+ SMU_13_0_7_ODFEATURE_FAN_SPEED_MIN = 1 << SMU_13_0_7_ODCAP_FAN_SPEED_MIN, //Minimum Fan Speed feature
+ SMU_13_0_7_ODFEATURE_TEMPERATURE_FAN = 1 << SMU_13_0_7_ODCAP_TEMPERATURE_FAN, //Fan Target Temperature Limit feature
+ SMU_13_0_7_ODFEATURE_TEMPERATURE_SYSTEM = 1 << SMU_13_0_7_ODCAP_TEMPERATURE_SYSTEM, //Operating Temperature Limit feature
+ SMU_13_0_7_ODFEATURE_MEMORY_TIMING_TUNE = 1 << SMU_13_0_7_ODCAP_MEMORY_TIMING_TUNE, //AC Timing Tuning feature
+ SMU_13_0_7_ODFEATURE_FAN_ZERO_RPM_CONTROL = 1 << SMU_13_0_7_ODCAP_FAN_ZERO_RPM_CONTROL, //Zero RPM feature
+ SMU_13_0_7_ODFEATURE_AUTO_UV_ENGINE = 1 << SMU_13_0_7_ODCAP_AUTO_UV_ENGINE, //Auto Under Volt GFXCLK feature
+ SMU_13_0_7_ODFEATURE_AUTO_OC_ENGINE = 1 << SMU_13_0_7_ODCAP_AUTO_OC_ENGINE, //Auto Over Clock GFXCLK feature
+ SMU_13_0_7_ODFEATURE_AUTO_OC_MEMORY = 1 << SMU_13_0_7_ODCAP_AUTO_OC_MEMORY, //Auto Over Clock MCLK feature
+ SMU_13_0_7_ODFEATURE_FAN_CURVE = 1 << SMU_13_0_7_ODCAP_FAN_CURVE, //Fan Curve feature
+ SMU_13_0_7_ODFEATURE_AUTO_FAN_ACOUSTIC_LIMIT = 1 << SMU_13_0_7_ODCAP_AUTO_FAN_ACOUSTIC_LIMIT, //Auto Fan Acoustic RPM feature
+ SMU_13_0_7_ODFEATURE_POWER_MODE = 1 << SMU_13_0_7_ODCAP_POWER_MODE, //Optimized GPU Power Mode feature
+ SMU_13_0_7_ODFEATURE_COUNT = 16,
+};
+
+#define SMU_13_0_7_MAX_ODFEATURE 32 //Maximum Number of OD Features
+
+enum SMU_13_0_7_ODSETTING_ID
+{
+ SMU_13_0_7_ODSETTING_GFXCLKFMAX = 0,
+ SMU_13_0_7_ODSETTING_GFXCLKFMIN,
+ SMU_13_0_7_ODSETTING_CUSTOM_GFX_VF_CURVE_A,
+ SMU_13_0_7_ODSETTING_CUSTOM_GFX_VF_CURVE_B,
+ SMU_13_0_7_ODSETTING_CUSTOM_GFX_VF_CURVE_C,
+ SMU_13_0_7_ODSETTING_CUSTOM_CURVE_VFT_FMIN,
+ SMU_13_0_7_ODSETTING_UCLKFMIN,
+ SMU_13_0_7_ODSETTING_UCLKFMAX,
+ SMU_13_0_7_ODSETTING_POWERPERCENTAGE,
+ SMU_13_0_7_ODSETTING_FANRPMMIN,
+ SMU_13_0_7_ODSETTING_FANRPMACOUSTICLIMIT,
+ SMU_13_0_7_ODSETTING_FANTARGETTEMPERATURE,
+ SMU_13_0_7_ODSETTING_OPERATINGTEMPMAX,
+ SMU_13_0_7_ODSETTING_ACTIMING,
+ SMU_13_0_7_ODSETTING_FAN_ZERO_RPM_CONTROL,
+ SMU_13_0_7_ODSETTING_AUTOUVENGINE,
+ SMU_13_0_7_ODSETTING_AUTOOCENGINE,
+ SMU_13_0_7_ODSETTING_AUTOOCMEMORY,
+ SMU_13_0_7_ODSETTING_FAN_CURVE_TEMPERATURE_1,
+ SMU_13_0_7_ODSETTING_FAN_CURVE_SPEED_1,
+ SMU_13_0_7_ODSETTING_FAN_CURVE_TEMPERATURE_2,
+ SMU_13_0_7_ODSETTING_FAN_CURVE_SPEED_2,
+ SMU_13_0_7_ODSETTING_FAN_CURVE_TEMPERATURE_3,
+ SMU_13_0_7_ODSETTING_FAN_CURVE_SPEED_3,
+ SMU_13_0_7_ODSETTING_FAN_CURVE_TEMPERATURE_4,
+ SMU_13_0_7_ODSETTING_FAN_CURVE_SPEED_4,
+ SMU_13_0_7_ODSETTING_FAN_CURVE_TEMPERATURE_5,
+ SMU_13_0_7_ODSETTING_FAN_CURVE_SPEED_5,
+ SMU_13_0_7_ODSETTING_AUTO_FAN_ACOUSTIC_LIMIT,
+ SMU_13_0_7_ODSETTING_POWER_MODE,
+ SMU_13_0_7_ODSETTING_COUNT,
+};
+#define SMU_13_0_7_MAX_ODSETTING 64 //Maximum Number of ODSettings
+
+enum SMU_13_0_7_PWRMODE_SETTING
+{
+ SMU_13_0_7_PMSETTING_POWER_LIMIT_QUIET = 0,
+ SMU_13_0_7_PMSETTING_POWER_LIMIT_BALANCE,
+ SMU_13_0_7_PMSETTING_POWER_LIMIT_TURBO,
+ SMU_13_0_7_PMSETTING_POWER_LIMIT_RAGE,
+ SMU_13_0_7_PMSETTING_ACOUSTIC_TEMP_QUIET,
+ SMU_13_0_7_PMSETTING_ACOUSTIC_TEMP_BALANCE,
+ SMU_13_0_7_PMSETTING_ACOUSTIC_TEMP_TURBO,
+ SMU_13_0_7_PMSETTING_ACOUSTIC_TEMP_RAGE,
+ SMU_13_0_7_PMSETTING_ACOUSTIC_TARGET_RPM_QUIET,
+ SMU_13_0_7_PMSETTING_ACOUSTIC_TARGET_RPM_BALANCE,
+ SMU_13_0_7_PMSETTING_ACOUSTIC_TARGET_RPM_TURBO,
+ SMU_13_0_7_PMSETTING_ACOUSTIC_TARGET_RPM_RAGE,
+ SMU_13_0_7_PMSETTING_ACOUSTIC_LIMIT_RPM_QUIET,
+ SMU_13_0_7_PMSETTING_ACOUSTIC_LIMIT_RPM_BALANCE,
+ SMU_13_0_7_PMSETTING_ACOUSTIC_LIMIT_RPM_TURBO,
+ SMU_13_0_7_PMSETTING_ACOUSTIC_LIMIT_RPM_RAGE,
+};
+#define SMU_13_0_7_MAX_PMSETTING 32 //Maximum Number of PowerMode Settings
+
+struct smu_13_0_7_overdrive_table
+{
+ uint8_t revision; //Revision = SMU_13_0_7_PP_OVERDRIVE_VERSION
+ uint8_t reserve[3]; //Zero filled field reserved for future use
+ uint32_t feature_count; //Total number of supported features
+ uint32_t setting_count; //Total number of supported settings
+ uint8_t cap[SMU_13_0_7_MAX_ODFEATURE]; //OD feature support flags
+ uint32_t max[SMU_13_0_7_MAX_ODSETTING]; //default maximum settings
+ uint32_t min[SMU_13_0_7_MAX_ODSETTING]; //default minimum settings
+ int16_t pm_setting[SMU_13_0_7_MAX_PMSETTING]; //Optimized power mode feature settings
+};
+
+enum SMU_13_0_7_PPCLOCK_ID
+{
+ SMU_13_0_7_PPCLOCK_GFXCLK = 0,
+ SMU_13_0_7_PPCLOCK_SOCCLK,
+ SMU_13_0_7_PPCLOCK_UCLK,
+ SMU_13_0_7_PPCLOCK_FCLK,
+ SMU_13_0_7_PPCLOCK_DCLK_0,
+ SMU_13_0_7_PPCLOCK_VCLK_0,
+ SMU_13_0_7_PPCLOCK_DCLK_1,
+ SMU_13_0_7_PPCLOCK_VCLK_1,
+ SMU_13_0_7_PPCLOCK_DCEFCLK,
+ SMU_13_0_7_PPCLOCK_DISPCLK,
+ SMU_13_0_7_PPCLOCK_PIXCLK,
+ SMU_13_0_7_PPCLOCK_PHYCLK,
+ SMU_13_0_7_PPCLOCK_DTBCLK,
+ SMU_13_0_7_PPCLOCK_COUNT,
+};
+#define SMU_13_0_7_MAX_PPCLOCK 16 //Maximum Number of PP Clocks
+
+struct smu_13_0_7_powerplay_table
+{
+ struct atom_common_table_header header; //For PLUM_BONITO, header.format_revision = 15, header.content_revision = 0
+ uint8_t table_revision; //For PLUM_BONITO, table_revision = 2
+ uint8_t padding;
+ uint16_t table_size; //Driver portion table size. The offset to smc_pptable including header size
+ uint32_t golden_pp_id; //PPGen use only: PP Table ID on the Golden Data Base
+ uint32_t golden_revision; //PPGen use only: PP Table Revision on the Golden Data Base
+ uint16_t format_id; //PPGen use only: PPTable for different ASICs. For PLUM_BONITO this should be 0x80
+ uint32_t platform_caps; //POWERPLAYABLE::ulPlatformCaps
+
+ uint8_t thermal_controller_type; //one of SMU_13_0_7_PP_THERMALCONTROLLER
+
+ uint16_t small_power_limit1;
+ uint16_t small_power_limit2;
+ uint16_t boost_power_limit; //For Gemini Board, when the slave adapter is in BACO mode, the master adapter will use this boost power limit instead of the default power limit to boost the power limit.
+ uint16_t software_shutdown_temp;
+
+ uint32_t reserve[45];
+
+ struct smu_13_0_7_overdrive_table overdrive_table;
+ uint8_t padding1;
+ PPTable_t smc_pptable; //PPTable_t in driver_if.h
+} __attribute__((packed));
+
+
+#endif
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
index ab3e9d8b831e..d68be8f8850e 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
@@ -371,6 +371,20 @@ static void sienna_cichlid_check_bxco_support(struct smu_context *smu)
}
}
+static void sienna_cichlid_check_fan_support(struct smu_context *smu)
+{
+ struct smu_table_context *table_context = &smu->smu_table;
+ PPTable_t *pptable = table_context->driver_pptable;
+ uint64_t features = *(uint64_t *) pptable->FeaturesToRun;
+
+ /* Fan control is not possible if PPTable has it disabled */
+ smu->adev->pm.no_fan =
+ !(features & (1ULL << FEATURE_FAN_CONTROL_BIT));
+ if (smu->adev->pm.no_fan)
+ dev_info_once(smu->adev->dev,
+ "PMFW based fan control disabled");
+}
+
static int sienna_cichlid_check_powerplay_table(struct smu_context *smu)
{
struct smu_table_context *table_context = &smu->smu_table;
@@ -381,6 +395,7 @@ static int sienna_cichlid_check_powerplay_table(struct smu_context *smu)
smu->dc_controlled_by_gpio = true;
sienna_cichlid_check_bxco_support(smu);
+ sienna_cichlid_check_fan_support(smu);
table_context->thermal_controller_type =
powerplay_table->thermal_controller_type;
@@ -410,7 +425,7 @@ static int sienna_cichlid_append_powerplay_table(struct smu_context *smu)
GET_PPTABLE_MEMBER(I2cControllers, &table_member);
memcpy(table_member, smc_dpm_table->I2cControllers,
sizeof(*smc_dpm_table) - sizeof(smc_dpm_table->table_header));
-
+
return 0;
}
@@ -570,6 +585,100 @@ static uint32_t sienna_cichlid_get_throttler_status_locked(struct smu_context *s
return throttler_status;
}
+static int sienna_cichlid_get_power_limit(struct smu_context *smu,
+ uint32_t *current_power_limit,
+ uint32_t *default_power_limit,
+ uint32_t *max_power_limit)
+{
+ struct smu_11_0_7_powerplay_table *powerplay_table =
+ (struct smu_11_0_7_powerplay_table *)smu->smu_table.power_play_table;
+ uint32_t power_limit, od_percent;
+ uint16_t *table_member;
+
+ GET_PPTABLE_MEMBER(SocketPowerLimitAc, &table_member);
+
+ if (smu_v11_0_get_current_power_limit(smu, &power_limit)) {
+ power_limit =
+ table_member[PPT_THROTTLER_PPT0];
+ }
+
+ if (current_power_limit)
+ *current_power_limit = power_limit;
+ if (default_power_limit)
+ *default_power_limit = power_limit;
+
+ if (max_power_limit) {
+ if (smu->od_enabled) {
+ od_percent =
+ le32_to_cpu(powerplay_table->overdrive_table.max[
+ SMU_11_0_7_ODSETTING_POWERPERCENTAGE]);
+
+ dev_dbg(smu->adev->dev, "ODSETTING_POWERPERCENTAGE: %d (default: %d)\n",
+ od_percent, power_limit);
+
+ power_limit *= (100 + od_percent);
+ power_limit /= 100;
+ }
+ *max_power_limit = power_limit;
+ }
+
+ return 0;
+}
+
+static void sienna_cichlid_get_smartshift_power_percentage(struct smu_context *smu,
+ uint32_t *apu_percent,
+ uint32_t *dgpu_percent)
+{
+ struct smu_table_context *smu_table = &smu->smu_table;
+ SmuMetrics_V4_t *metrics_v4 =
+ &(((SmuMetricsExternal_t *)(smu_table->metrics_table))->SmuMetrics_V4);
+ uint16_t powerRatio = 0;
+ uint16_t apu_power_limit = 0;
+ uint16_t dgpu_power_limit = 0;
+ uint32_t apu_boost = 0;
+ uint32_t dgpu_boost = 0;
+ uint32_t cur_power_limit;
+
+ if (metrics_v4->ApuSTAPMSmartShiftLimit != 0) {
+ sienna_cichlid_get_power_limit(smu, &cur_power_limit, NULL, NULL);
+ apu_power_limit = metrics_v4->ApuSTAPMLimit;
+ dgpu_power_limit = cur_power_limit;
+ powerRatio = (((apu_power_limit +
+ dgpu_power_limit) * 100) /
+ metrics_v4->ApuSTAPMSmartShiftLimit);
+ if (powerRatio > 100) {
+ apu_power_limit = (apu_power_limit * 100) /
+ powerRatio;
+ dgpu_power_limit = (dgpu_power_limit * 100) /
+ powerRatio;
+ }
+ if (metrics_v4->AverageApuSocketPower > apu_power_limit &&
+ apu_power_limit != 0) {
+ apu_boost = ((metrics_v4->AverageApuSocketPower -
+ apu_power_limit) * 100) /
+ apu_power_limit;
+ if (apu_boost > 100)
+ apu_boost = 100;
+ }
+
+ if (metrics_v4->AverageSocketPower > dgpu_power_limit &&
+ dgpu_power_limit != 0) {
+ dgpu_boost = ((metrics_v4->AverageSocketPower -
+ dgpu_power_limit) * 100) /
+ dgpu_power_limit;
+ if (dgpu_boost > 100)
+ dgpu_boost = 100;
+ }
+
+ if (dgpu_boost >= apu_boost)
+ apu_boost = 0;
+ else
+ dgpu_boost = 0;
+ }
+ *apu_percent = apu_boost;
+ *dgpu_percent = dgpu_boost;
+}
+
static int sienna_cichlid_get_smu_metrics_data(struct smu_context *smu,
MetricsMember_t member,
uint32_t *value)
@@ -585,6 +694,8 @@ static int sienna_cichlid_get_smu_metrics_data(struct smu_context *smu,
bool use_metrics_v3 = false;
uint16_t average_gfx_activity;
int ret = 0;
+ uint32_t apu_percent = 0;
+ uint32_t dgpu_percent = 0;
if ((smu->adev->ip_versions[MP1_HWIP][0] == IP_VERSION(11, 0, 7)) &&
(smu->smc_fw_version >= 0x3A4900))
@@ -723,6 +834,15 @@ static int sienna_cichlid_get_smu_metrics_data(struct smu_context *smu,
/* Only supported in 0x3A5300+, metrics_v3 requires 0x3A4900+ */
*value = use_metrics_v3 ? metrics_v3->PublicSerialNumLower32 : 0;
break;
+ case METRICS_SS_APU_SHARE:
+ sienna_cichlid_get_smartshift_power_percentage(smu, &apu_percent, &dgpu_percent);
+ *value = apu_percent;
+ break;
+ case METRICS_SS_DGPU_SHARE:
+ sienna_cichlid_get_smartshift_power_percentage(smu, &apu_percent, &dgpu_percent);
+ *value = dgpu_percent;
+ break;
+
default:
*value = UINT_MAX;
break;
@@ -1713,6 +1833,7 @@ static int sienna_cichlid_read_sensor(struct smu_context *smu,
{
int ret = 0;
uint16_t *temp;
+ struct amdgpu_device *adev = smu->adev;
if(!data || !size)
return -EINVAL;
@@ -1773,6 +1894,24 @@ static int sienna_cichlid_read_sensor(struct smu_context *smu,
ret = smu_v11_0_get_gfx_vdd(smu, (uint32_t *)data);
*size = 4;
break;
+ case AMDGPU_PP_SENSOR_SS_APU_SHARE:
+ if (adev->ip_versions[MP1_HWIP][0] != IP_VERSION(11, 0, 7)) {
+ ret = sienna_cichlid_get_smu_metrics_data(smu,
+ METRICS_SS_APU_SHARE, (uint32_t *)data);
+ *size = 4;
+ } else {
+ ret = -EOPNOTSUPP;
+ }
+ break;
+ case AMDGPU_PP_SENSOR_SS_DGPU_SHARE:
+ if (adev->ip_versions[MP1_HWIP][0] != IP_VERSION(11, 0, 7)) {
+ ret = sienna_cichlid_get_smu_metrics_data(smu,
+ METRICS_SS_DGPU_SHARE, (uint32_t *)data);
+ *size = 4;
+ } else {
+ ret = -EOPNOTSUPP;
+ }
+ break;
default:
ret = -EOPNOTSUPP;
break;
@@ -1892,43 +2031,6 @@ static int sienna_cichlid_display_disable_memory_clock_switch(struct smu_context
return ret;
}
-static int sienna_cichlid_get_power_limit(struct smu_context *smu,
- uint32_t *current_power_limit,
- uint32_t *default_power_limit,
- uint32_t *max_power_limit)
-{
- struct smu_11_0_7_powerplay_table *powerplay_table =
- (struct smu_11_0_7_powerplay_table *)smu->smu_table.power_play_table;
- uint32_t power_limit, od_percent;
- uint16_t *table_member;
-
- GET_PPTABLE_MEMBER(SocketPowerLimitAc, &table_member);
-
- if (smu_v11_0_get_current_power_limit(smu, &power_limit)) {
- power_limit =
- table_member[PPT_THROTTLER_PPT0];
- }
-
- if (current_power_limit)
- *current_power_limit = power_limit;
- if (default_power_limit)
- *default_power_limit = power_limit;
-
- if (max_power_limit) {
- if (smu->od_enabled) {
- od_percent = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_7_ODSETTING_POWERPERCENTAGE]);
-
- dev_dbg(smu->adev->dev, "ODSETTING_POWERPERCENTAGE: %d (default: %d)\n", od_percent, power_limit);
-
- power_limit *= (100 + od_percent);
- power_limit /= 100;
- }
- *max_power_limit = power_limit;
- }
-
- return 0;
-}
-
static int sienna_cichlid_update_pcie_parameters(struct smu_context *smu,
uint32_t pcie_gen_cap,
uint32_t pcie_width_cap)
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c
index fd6c44ece168..012e3bd99cc2 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c
@@ -1119,6 +1119,39 @@ static int renoir_get_power_profile_mode(struct smu_context *smu,
return size;
}
+static void renoir_get_ss_power_percent(SmuMetrics_t *metrics,
+ uint32_t *apu_percent, uint32_t *dgpu_percent)
+{
+ uint32_t apu_boost = 0;
+ uint32_t dgpu_boost = 0;
+ uint16_t apu_limit = 0;
+ uint16_t dgpu_limit = 0;
+ uint16_t apu_power = 0;
+ uint16_t dgpu_power = 0;
+
+ apu_power = metrics->ApuPower;
+ apu_limit = metrics->StapmOriginalLimit;
+ if (apu_power > apu_limit && apu_limit != 0)
+ apu_boost = ((apu_power - apu_limit) * 100) / apu_limit;
+ apu_boost = (apu_boost > 100) ? 100 : apu_boost;
+
+ dgpu_power = metrics->dGpuPower;
+ if (metrics->StapmCurrentLimit > metrics->StapmOriginalLimit)
+ dgpu_limit = metrics->StapmCurrentLimit - metrics->StapmOriginalLimit;
+ if (dgpu_power > dgpu_limit && dgpu_limit != 0)
+ dgpu_boost = ((dgpu_power - dgpu_limit) * 100) / dgpu_limit;
+ dgpu_boost = (dgpu_boost > 100) ? 100 : dgpu_boost;
+
+ if (dgpu_boost >= apu_boost)
+ apu_boost = 0;
+ else
+ dgpu_boost = 0;
+
+ *apu_percent = apu_boost;
+ *dgpu_percent = dgpu_boost;
+}
+
+
static int renoir_get_smu_metrics_data(struct smu_context *smu,
MetricsMember_t member,
uint32_t *value)
@@ -1127,6 +1160,9 @@ static int renoir_get_smu_metrics_data(struct smu_context *smu,
SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table;
int ret = 0;
+ uint32_t apu_percent = 0;
+ uint32_t dgpu_percent = 0;
+
ret = smu_cmn_get_metrics_table(smu,
NULL,
@@ -1171,26 +1207,18 @@ static int renoir_get_smu_metrics_data(struct smu_context *smu,
*value = metrics->Voltage[1];
break;
case METRICS_SS_APU_SHARE:
- /* return the percentage of APU power with respect to APU's power limit.
- * percentage is reported, this isn't boost value. Smartshift power
- * boost/shift is only when the percentage is more than 100.
+ /* return the percentage of APU power boost
+ * with respect to APU's power limit.
*/
- if (metrics->StapmOriginalLimit > 0)
- *value = (metrics->ApuPower * 100) / metrics->StapmOriginalLimit;
- else
- *value = 0;
+ renoir_get_ss_power_percent(metrics, &apu_percent, &dgpu_percent);
+ *value = apu_percent;
break;
case METRICS_SS_DGPU_SHARE:
- /* return the percentage of dGPU power with respect to dGPU's power limit.
- * percentage is reported, this isn't boost value. Smartshift power
- * boost/shift is only when the percentage is more than 100.
+ /* return the percentage of dGPU power boost
+ * with respect to dGPU's power limit.
*/
- if ((metrics->dGpuPower > 0) &&
- (metrics->StapmCurrentLimit > metrics->StapmOriginalLimit))
- *value = (metrics->dGpuPower * 100) /
- (metrics->StapmCurrentLimit - metrics->StapmOriginalLimit);
- else
- *value = 0;
+ renoir_get_ss_power_percent(metrics, &apu_percent, &dgpu_percent);
+ *value = dgpu_percent;
break;
default:
*value = UINT_MAX;
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/Makefile b/drivers/gpu/drm/amd/pm/swsmu/smu13/Makefile
index 613cdd0d8e83..9043f6ef1aee 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/Makefile
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/Makefile
@@ -23,7 +23,8 @@
# Makefile for the 'smu manager' sub-component of powerplay.
# It provides the smu management services for the driver.
-SMU13_MGR = smu_v13_0.o aldebaran_ppt.o yellow_carp_ppt.o smu_v13_0_5_ppt.o
+SMU13_MGR = smu_v13_0.o aldebaran_ppt.o yellow_carp_ppt.o smu_v13_0_0_ppt.o smu_v13_0_4_ppt.o \
+ smu_v13_0_5_ppt.o smu_v13_0_7_ppt.o
AMD_SWSMU_SMU13MGR = $(addprefix $(AMD_SWSMU_PATH)/smu13/,$(SMU13_MGR))
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.h b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.h
index 33a85d57cf15..31e991bde3e5 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.h
@@ -28,7 +28,7 @@
#define ALDEBARAN_UMD_PSTATE_MCLK_LEVEL 0x2
#define MAX_DPM_NUMBER 16
-#define MAX_PCIE_CONF 2
+#define ALDEBARAN_MAX_PCIE_CONF 2
struct aldebaran_dpm_level {
bool enabled;
@@ -51,9 +51,9 @@ struct aldebaran_single_dpm_table {
struct aldebaran_pcie_table {
uint16_t count;
- uint8_t pcie_gen[MAX_PCIE_CONF];
- uint8_t pcie_lane[MAX_PCIE_CONF];
- uint32_t lclk[MAX_PCIE_CONF];
+ uint8_t pcie_gen[ALDEBARAN_MAX_PCIE_CONF];
+ uint8_t pcie_lane[ALDEBARAN_MAX_PCIE_CONF];
+ uint32_t lclk[ALDEBARAN_MAX_PCIE_CONF];
};
struct aldebaran_dpm_table {
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c
index cf09e30bdfe0..ae6321af9d88 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c
@@ -57,6 +57,8 @@
#undef pr_debug
MODULE_FIRMWARE("amdgpu/aldebaran_smc.bin");
+MODULE_FIRMWARE("amdgpu/smu_13_0_0.bin");
+MODULE_FIRMWARE("amdgpu/smu_13_0_7.bin");
#define SMU13_VOLTAGE_SCALE 4
@@ -73,11 +75,15 @@ MODULE_FIRMWARE("amdgpu/aldebaran_smc.bin");
static const int link_width[] = {0, 1, 2, 4, 8, 12, 16};
static const int link_speed[] = {25, 50, 80, 160};
+static int smu_v13_0_get_pptable_from_firmware(struct smu_context *smu, void **table, uint32_t *size,
+ uint32_t pptable_id);
+
int smu_v13_0_init_microcode(struct smu_context *smu)
{
struct amdgpu_device *adev = smu->adev;
const char *chip_name;
char fw_name[30];
+ char ucode_prefix[30];
int err = 0;
const struct smc_firmware_header_v1_0 *hdr;
const struct common_firmware_header *header;
@@ -89,15 +95,14 @@ int smu_v13_0_init_microcode(struct smu_context *smu)
switch (adev->ip_versions[MP1_HWIP][0]) {
case IP_VERSION(13, 0, 2):
- chip_name = "aldebaran";
+ chip_name = "aldebaran_smc";
break;
default:
- dev_err(adev->dev, "Unsupported IP version 0x%x\n",
- adev->ip_versions[MP1_HWIP][0]);
- return -EINVAL;
+ amdgpu_ucode_ip_version_decode(adev, MP1_HWIP, ucode_prefix, sizeof(ucode_prefix));
+ chip_name = ucode_prefix;
}
- snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_smc.bin", chip_name);
+ snprintf(fw_name, sizeof(fw_name), "amdgpu/%s.bin", chip_name);
err = request_firmware(&adev->pm.fw, fw_name, adev->dev);
if (err)
@@ -176,6 +181,69 @@ int smu_v13_0_load_microcode(struct smu_context *smu)
if (i == adev->usec_timeout)
return -ETIME;
#endif
+
+ return 0;
+}
+
+int smu_v13_0_init_pptable_microcode(struct smu_context *smu)
+{
+ struct amdgpu_device *adev = smu->adev;
+ struct amdgpu_firmware_info *ucode = NULL;
+ uint32_t size = 0, pptable_id = 0;
+ int ret = 0;
+ void *table;
+
+ /* doesn't need to load smu firmware in IOV mode */
+ if (amdgpu_sriov_vf(adev))
+ return 0;
+
+ if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
+ return 0;
+
+ if (!adev->scpm_enabled)
+ return 0;
+
+ /* override pptable_id from driver parameter */
+ if (amdgpu_smu_pptable_id >= 0) {
+ pptable_id = amdgpu_smu_pptable_id;
+ dev_info(adev->dev, "override pptable id %d\n", pptable_id);
+ } else {
+ pptable_id = smu->smu_table.boot_values.pp_table_id;
+
+ if (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 7) &&
+ pptable_id == 3667)
+ pptable_id = 36671;
+
+ if (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 7) &&
+ pptable_id == 3688)
+ pptable_id = 36881;
+ /*
+ * Temporary solution for SMU V13.0.0:
+ * - use 99991 signed pptable when SCPM enabled
+ * TODO: drop this when the pptable carried in vbios
+ * is ready.
+ */
+ if (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 0))
+ pptable_id = 99991;
+ }
+
+ /* "pptable_id == 0" means vbios carries the pptable. */
+ if (!pptable_id)
+ return 0;
+
+ ret = smu_v13_0_get_pptable_from_firmware(smu, &table, &size, pptable_id);
+ if (ret)
+ return ret;
+
+ smu->pptable_firmware.data = table;
+ smu->pptable_firmware.size = size;
+
+ ucode = &adev->firmware.ucode[AMDGPU_UCODE_ID_PPTABLE];
+ ucode->ucode_id = AMDGPU_UCODE_ID_PPTABLE;
+ ucode->fw = &smu->pptable_firmware;
+ adev->firmware.fw_size +=
+ ALIGN(smu->pptable_firmware.size, PAGE_SIZE);
+
return 0;
}
@@ -216,11 +284,20 @@ int smu_v13_0_check_fw_version(struct smu_context *smu)
case IP_VERSION(13, 0, 2):
smu->smc_driver_if_version = SMU13_DRIVER_IF_VERSION_ALDE;
break;
+ case IP_VERSION(13, 0, 0):
+ smu->smc_driver_if_version = SMU13_DRIVER_IF_VERSION_SMU_V13_0_0;
+ break;
+ case IP_VERSION(13, 0, 7):
+ smu->smc_driver_if_version = SMU13_DRIVER_IF_VERSION_SMU_V13_0_7;
+ break;
case IP_VERSION(13, 0, 1):
case IP_VERSION(13, 0, 3):
case IP_VERSION(13, 0, 8):
smu->smc_driver_if_version = SMU13_DRIVER_IF_VERSION_YELLOW_CARP;
break;
+ case IP_VERSION(13, 0, 4):
+ smu->smc_driver_if_version = SMU13_DRIVER_IF_VERSION_SMU_V13_0_4;
+ break;
case IP_VERSION(13, 0, 5):
smu->smc_driver_if_version = SMU13_DRIVER_IF_VERSION_SMU_V13_0_5;
break;
@@ -255,6 +332,21 @@ int smu_v13_0_check_fw_version(struct smu_context *smu)
return ret;
}
+static int smu_v13_0_set_pptable_v2_0(struct smu_context *smu, void **table, uint32_t *size)
+{
+ struct amdgpu_device *adev = smu->adev;
+ uint32_t ppt_offset_bytes;
+ const struct smc_firmware_header_v2_0 *v2;
+
+ v2 = (const struct smc_firmware_header_v2_0 *) adev->pm.fw->data;
+
+ ppt_offset_bytes = le32_to_cpu(v2->ppt_offset_bytes);
+ *size = le32_to_cpu(v2->ppt_size_bytes);
+ *table = (uint8_t *)v2 + ppt_offset_bytes;
+
+ return 0;
+}
+
static int smu_v13_0_set_pptable_v2_1(struct smu_context *smu, void **table,
uint32_t *size, uint32_t pptable_id)
{
@@ -327,6 +419,9 @@ static int smu_v13_0_get_pptable_from_firmware(struct smu_context *smu, void **t
}
switch (version_minor) {
+ case 0:
+ ret = smu_v13_0_set_pptable_v2_0(smu, table, size);
+ break;
case 1:
ret = smu_v13_0_set_pptable_v2_1(smu, table, size, pptable_id);
break;
@@ -351,10 +446,19 @@ int smu_v13_0_setup_pptable(struct smu_context *smu)
dev_info(adev->dev, "override pptable id %d\n", pptable_id);
} else {
pptable_id = smu->smu_table.boot_values.pp_table_id;
+
+ /*
+ * Temporary solution for SMU V13.0.0:
+ * - use 9999 unsigned pptable when SCPM disabled
+ * TODO: drop this when the pptable carried in vbios
+ * is ready.
+ */
+ if (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 0))
+ pptable_id = 9999;
}
/* force using vbios pptable in sriov mode */
- if (amdgpu_sriov_vf(adev) || !pptable_id)
+ if ((amdgpu_sriov_vf(adev) || !pptable_id) && (amdgpu_emu_mode != 1))
ret = smu_v13_0_get_pptable_from_vbios(smu, &table, &size);
else
ret = smu_v13_0_get_pptable_from_firmware(smu, &table, &size, pptable_id);
@@ -407,8 +511,17 @@ int smu_v13_0_init_smc_tables(struct smu_context *smu)
}
}
+ smu_table->combo_pptable =
+ kzalloc(tables[SMU_TABLE_COMBO_PPTABLE].size, GFP_KERNEL);
+ if (!smu_table->combo_pptable) {
+ ret = -ENOMEM;
+ goto err4_out;
+ }
+
return 0;
+err4_out:
+ kfree(smu_table->boot_overdrive_table);
err3_out:
kfree(smu_table->overdrive_table);
err2_out:
@@ -425,11 +538,13 @@ int smu_v13_0_fini_smc_tables(struct smu_context *smu)
struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
kfree(smu_table->gpu_metrics_table);
+ kfree(smu_table->combo_pptable);
kfree(smu_table->boot_overdrive_table);
kfree(smu_table->overdrive_table);
kfree(smu_table->max_sustainable_clocks);
kfree(smu_table->driver_pptable);
smu_table->gpu_metrics_table = NULL;
+ smu_table->combo_pptable = NULL;
smu_table->boot_overdrive_table = NULL;
smu_table->overdrive_table = NULL;
smu_table->max_sustainable_clocks = NULL;
@@ -488,32 +603,6 @@ int smu_v13_0_fini_power(struct smu_context *smu)
return 0;
}
-static int smu_v13_0_atom_get_smu_clockinfo(struct amdgpu_device *adev,
- uint8_t clk_id,
- uint8_t syspll_id,
- uint32_t *clk_freq)
-{
- struct atom_get_smu_clock_info_parameters_v3_1 input = {0};
- struct atom_get_smu_clock_info_output_parameters_v3_1 *output;
- int ret, index;
-
- input.clk_id = clk_id;
- input.syspll_id = syspll_id;
- input.command = GET_SMU_CLOCK_INFO_V3_1_GET_CLOCK_FREQ;
- index = get_index_into_master_table(atom_master_list_of_command_functions_v2_1,
- getsmuclockinfo);
-
- ret = amdgpu_atom_execute_table(adev->mode_info.atom_context, index,
- (uint32_t *)&input);
- if (ret)
- return -EINVAL;
-
- output = (struct atom_get_smu_clock_info_output_parameters_v3_1 *)&input;
- *clk_freq = le32_to_cpu(output->atom_smu_outputclkfreq.smu_clock_freq_hz) / 10000;
-
- return 0;
-}
-
int smu_v13_0_get_vbios_bootup_values(struct smu_context *smu)
{
int ret, index;
@@ -523,6 +612,8 @@ int smu_v13_0_get_vbios_bootup_values(struct smu_context *smu)
struct atom_firmware_info_v3_4 *v_3_4;
struct atom_firmware_info_v3_3 *v_3_3;
struct atom_firmware_info_v3_1 *v_3_1;
+ struct atom_smu_info_v3_6 *smu_info_v3_6;
+ struct atom_smu_info_v4_0 *smu_info_v4_0;
index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
firmwareinfo);
@@ -588,37 +679,31 @@ int smu_v13_0_get_vbios_bootup_values(struct smu_context *smu)
smu->smu_table.boot_values.format_revision = header->format_revision;
smu->smu_table.boot_values.content_revision = header->content_revision;
- smu_v13_0_atom_get_smu_clockinfo(smu->adev,
- (uint8_t)SMU11_SYSPLL0_SOCCLK_ID,
- (uint8_t)0,
- &smu->smu_table.boot_values.socclk);
-
- smu_v13_0_atom_get_smu_clockinfo(smu->adev,
- (uint8_t)SMU11_SYSPLL0_DCEFCLK_ID,
- (uint8_t)0,
- &smu->smu_table.boot_values.dcefclk);
-
- smu_v13_0_atom_get_smu_clockinfo(smu->adev,
- (uint8_t)SMU11_SYSPLL0_ECLK_ID,
- (uint8_t)0,
- &smu->smu_table.boot_values.eclk);
-
- smu_v13_0_atom_get_smu_clockinfo(smu->adev,
- (uint8_t)SMU11_SYSPLL0_VCLK_ID,
- (uint8_t)0,
- &smu->smu_table.boot_values.vclk);
-
- smu_v13_0_atom_get_smu_clockinfo(smu->adev,
- (uint8_t)SMU11_SYSPLL0_DCLK_ID,
- (uint8_t)0,
- &smu->smu_table.boot_values.dclk);
-
- if ((smu->smu_table.boot_values.format_revision == 3) &&
- (smu->smu_table.boot_values.content_revision >= 2))
- smu_v13_0_atom_get_smu_clockinfo(smu->adev,
- (uint8_t)SMU11_SYSPLL1_0_FCLK_ID,
- (uint8_t)SMU11_SYSPLL1_2_ID,
- &smu->smu_table.boot_values.fclk);
+ index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
+ smu_info);
+ if (!amdgpu_atombios_get_data_table(smu->adev, index, &size, &frev, &crev,
+ (uint8_t **)&header)) {
+
+ if ((frev == 3) && (crev == 6)) {
+ smu_info_v3_6 = (struct atom_smu_info_v3_6 *)header;
+
+ smu->smu_table.boot_values.socclk = smu_info_v3_6->bootup_socclk_10khz;
+ smu->smu_table.boot_values.vclk = smu_info_v3_6->bootup_vclk_10khz;
+ smu->smu_table.boot_values.dclk = smu_info_v3_6->bootup_dclk_10khz;
+ smu->smu_table.boot_values.fclk = smu_info_v3_6->bootup_fclk_10khz;
+ } else if ((frev == 4) && (crev == 0)) {
+ smu_info_v4_0 = (struct atom_smu_info_v4_0 *)header;
+
+ smu->smu_table.boot_values.socclk = smu_info_v4_0->bootup_socclk_10khz;
+ smu->smu_table.boot_values.dcefclk = smu_info_v4_0->bootup_dcefclk_10khz;
+ smu->smu_table.boot_values.vclk = smu_info_v4_0->bootup_vclk0_10khz;
+ smu->smu_table.boot_values.dclk = smu_info_v4_0->bootup_dclk0_10khz;
+ smu->smu_table.boot_values.fclk = smu_info_v4_0->bootup_fclk_10khz;
+ } else {
+ dev_warn(smu->adev->dev, "Unexpected and unhandled version: %d.%d\n",
+ (uint32_t)frev, (uint32_t)crev);
+ }
+ }
return 0;
}
@@ -719,7 +804,6 @@ int smu_v13_0_init_display_count(struct smu_context *smu, uint32_t count)
return ret;
}
-
int smu_v13_0_set_allowed_mask(struct smu_context *smu)
{
struct smu_feature *feature = &smu->smu_feature;
@@ -749,9 +833,12 @@ int smu_v13_0_gfx_off_control(struct smu_context *smu, bool enable)
struct amdgpu_device *adev = smu->adev;
switch (adev->ip_versions[MP1_HWIP][0]) {
+ case IP_VERSION(13, 0, 0):
case IP_VERSION(13, 0, 1):
case IP_VERSION(13, 0, 3):
+ case IP_VERSION(13, 0, 4):
case IP_VERSION(13, 0, 5):
+ case IP_VERSION(13, 0, 7):
case IP_VERSION(13, 0, 8):
if (!(adev->pm.pp_feature & PP_GFXOFF_MASK))
return 0;
@@ -1081,15 +1168,14 @@ smu_v13_0_set_fan_static_mode(struct smu_context *smu, uint32_t mode)
return 0;
}
- int
-smu_v13_0_set_fan_speed_percent(struct smu_context *smu, uint32_t speed)
+int smu_v13_0_set_fan_speed_pwm(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;
+ speed = MIN(speed, 255);
if (smu_v13_0_auto_fan_control(smu, 0))
return -EINVAL;
@@ -1100,7 +1186,7 @@ smu_v13_0_set_fan_speed_percent(struct smu_context *smu, uint32_t speed)
return -EINVAL;
tmp64 = (uint64_t)speed * duty100;
- do_div(tmp64, 100);
+ do_div(tmp64, 255);
duty = (uint32_t)tmp64;
WREG32_SOC15(THM, 0, regCG_FDO_CTRL0,
@@ -1118,7 +1204,7 @@ smu_v13_0_set_fan_control_mode(struct smu_context *smu,
switch (mode) {
case AMD_FAN_CTRL_NONE:
- ret = smu_v13_0_set_fan_speed_percent(smu, 100);
+ ret = smu_v13_0_set_fan_speed_pwm(smu, 255);
break;
case AMD_FAN_CTRL_MANUAL:
ret = smu_v13_0_auto_fan_control(smu, 0);
@@ -1142,8 +1228,8 @@ int smu_v13_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;
+ int ret;
if (!speed)
return -EINVAL;
@@ -1159,9 +1245,7 @@ int smu_v13_0_set_fan_speed_rpm(struct smu_context *smu,
CG_TACH_CTRL, TARGET_PERIOD,
tach_period));
- ret = smu_v13_0_set_fan_static_mode(smu, FDO_PWM_MODE_STATIC_RPM);
-
- return ret;
+ return smu_v13_0_set_fan_static_mode(smu, FDO_PWM_MODE_STATIC_RPM);
}
int smu_v13_0_set_xgmi_pstate(struct smu_context *smu,
@@ -1436,19 +1520,6 @@ int smu_v13_0_wait_for_event(struct smu_context *smu, enum smu_event_type event,
return ret;
}
-int smu_v13_0_mode2_reset(struct smu_context *smu)
-{
- int ret;
-
- ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_GfxDeviceDriverReset,
- SMU_RESET_MODE_2, NULL);
- /*TODO: mode2 reset wait time should be shorter, add ASIC specific func if required */
- if (!ret)
- msleep(SMU13_MODE1_RESET_WAIT_TIME_IN_MS);
-
- return ret;
-}
-
int smu_v13_0_get_dpm_ultimate_freq(struct smu_context *smu, enum smu_clk_type clk_type,
uint32_t *min, uint32_t *max)
{
@@ -1493,7 +1564,16 @@ int smu_v13_0_get_dpm_ultimate_freq(struct smu_context *smu, enum smu_clk_type c
param = (clk_id & 0xffff) << 16;
if (max) {
- ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_GetMaxDpmFreq, param, max);
+ if (smu->adev->pm.ac_power)
+ ret = smu_cmn_send_smc_msg_with_param(smu,
+ SMU_MSG_GetMaxDpmFreq,
+ param,
+ max);
+ else
+ ret = smu_cmn_send_smc_msg_with_param(smu,
+ SMU_MSG_GetDcModeMaxDpmFreq,
+ param,
+ max);
if (ret)
goto failed;
}
@@ -1595,24 +1675,39 @@ int smu_v13_0_set_performance_level(struct smu_context *smu,
&dpm_context->dpm_tables.uclk_table;
struct smu_13_0_dpm_table *soc_table =
&dpm_context->dpm_tables.soc_table;
+ struct smu_13_0_dpm_table *vclk_table =
+ &dpm_context->dpm_tables.vclk_table;
+ struct smu_13_0_dpm_table *dclk_table =
+ &dpm_context->dpm_tables.dclk_table;
+ struct smu_13_0_dpm_table *fclk_table =
+ &dpm_context->dpm_tables.fclk_table;
struct smu_umd_pstate_table *pstate_table =
&smu->pstate_table;
struct amdgpu_device *adev = smu->adev;
uint32_t sclk_min = 0, sclk_max = 0;
uint32_t mclk_min = 0, mclk_max = 0;
uint32_t socclk_min = 0, socclk_max = 0;
- int ret = 0;
+ uint32_t vclk_min = 0, vclk_max = 0;
+ uint32_t dclk_min = 0, dclk_max = 0;
+ uint32_t fclk_min = 0, fclk_max = 0;
+ int ret = 0, i;
switch (level) {
case AMD_DPM_FORCED_LEVEL_HIGH:
sclk_min = sclk_max = gfx_table->max;
mclk_min = mclk_max = mem_table->max;
socclk_min = socclk_max = soc_table->max;
+ vclk_min = vclk_max = vclk_table->max;
+ dclk_min = dclk_max = dclk_table->max;
+ fclk_min = fclk_max = fclk_table->max;
break;
case AMD_DPM_FORCED_LEVEL_LOW:
sclk_min = sclk_max = gfx_table->min;
mclk_min = mclk_max = mem_table->min;
socclk_min = socclk_max = soc_table->min;
+ vclk_min = vclk_max = vclk_table->min;
+ dclk_min = dclk_max = dclk_table->min;
+ fclk_min = fclk_max = fclk_table->min;
break;
case AMD_DPM_FORCED_LEVEL_AUTO:
sclk_min = gfx_table->min;
@@ -1621,11 +1716,20 @@ int smu_v13_0_set_performance_level(struct smu_context *smu,
mclk_max = mem_table->max;
socclk_min = soc_table->min;
socclk_max = soc_table->max;
+ vclk_min = vclk_table->min;
+ vclk_max = vclk_table->max;
+ dclk_min = dclk_table->min;
+ dclk_max = dclk_table->max;
+ fclk_min = fclk_table->min;
+ fclk_max = fclk_table->max;
break;
case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD:
sclk_min = sclk_max = pstate_table->gfxclk_pstate.standard;
mclk_min = mclk_max = pstate_table->uclk_pstate.standard;
socclk_min = socclk_max = pstate_table->socclk_pstate.standard;
+ vclk_min = vclk_max = pstate_table->vclk_pstate.standard;
+ dclk_min = dclk_max = pstate_table->dclk_pstate.standard;
+ fclk_min = fclk_max = pstate_table->fclk_pstate.standard;
break;
case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK:
sclk_min = sclk_max = pstate_table->gfxclk_pstate.min;
@@ -1637,6 +1741,9 @@ int smu_v13_0_set_performance_level(struct smu_context *smu,
sclk_min = sclk_max = pstate_table->gfxclk_pstate.peak;
mclk_min = mclk_max = pstate_table->uclk_pstate.peak;
socclk_min = socclk_max = pstate_table->socclk_pstate.peak;
+ vclk_min = vclk_max = pstate_table->vclk_pstate.peak;
+ dclk_min = dclk_max = pstate_table->dclk_pstate.peak;
+ fclk_min = fclk_max = pstate_table->fclk_pstate.peak;
break;
case AMD_DPM_FORCED_LEVEL_MANUAL:
case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT:
@@ -1646,8 +1753,17 @@ int smu_v13_0_set_performance_level(struct smu_context *smu,
return -EINVAL;
}
- mclk_min = mclk_max = 0;
- socclk_min = socclk_max = 0;
+ /*
+ * Unset those settings for SMU 13.0.2. As soft limits settings
+ * for those clock domains are not supported.
+ */
+ if (smu->adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 2)) {
+ mclk_min = mclk_max = 0;
+ socclk_min = socclk_max = 0;
+ vclk_min = vclk_max = 0;
+ dclk_min = dclk_max = 0;
+ fclk_min = fclk_max = 0;
+ }
if (sclk_min && sclk_max) {
ret = smu_v13_0_set_soft_freq_limited_range(smu,
@@ -1685,6 +1801,48 @@ int smu_v13_0_set_performance_level(struct smu_context *smu,
pstate_table->socclk_pstate.curr.max = socclk_max;
}
+ if (vclk_min && vclk_max) {
+ for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
+ if (adev->vcn.harvest_config & (1 << i))
+ continue;
+ ret = smu_v13_0_set_soft_freq_limited_range(smu,
+ i ? SMU_VCLK1 : SMU_VCLK,
+ vclk_min,
+ vclk_max);
+ if (ret)
+ return ret;
+ }
+ pstate_table->vclk_pstate.curr.min = vclk_min;
+ pstate_table->vclk_pstate.curr.max = vclk_max;
+ }
+
+ if (dclk_min && dclk_max) {
+ for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
+ if (adev->vcn.harvest_config & (1 << i))
+ continue;
+ ret = smu_v13_0_set_soft_freq_limited_range(smu,
+ i ? SMU_DCLK1 : SMU_DCLK,
+ dclk_min,
+ dclk_max);
+ if (ret)
+ return ret;
+ }
+ pstate_table->dclk_pstate.curr.min = dclk_min;
+ pstate_table->dclk_pstate.curr.max = dclk_max;
+ }
+
+ if (fclk_min && fclk_max) {
+ ret = smu_v13_0_set_soft_freq_limited_range(smu,
+ SMU_FCLK,
+ fclk_min,
+ fclk_max);
+ if (ret)
+ return ret;
+
+ pstate_table->fclk_pstate.curr.min = fclk_min;
+ pstate_table->fclk_pstate.curr.max = fclk_max;
+ }
+
return ret;
}
@@ -1705,10 +1863,10 @@ int smu_v13_0_set_power_source(struct smu_context *smu,
NULL);
}
-int smu_v13_0_get_dpm_freq_by_index(struct smu_context *smu,
- enum smu_clk_type clk_type,
- uint16_t level,
- uint32_t *value)
+static int smu_v13_0_get_dpm_freq_by_index(struct smu_context *smu,
+ enum smu_clk_type clk_type,
+ uint16_t level,
+ uint32_t *value)
{
int ret = 0, clk_id = 0;
uint32_t param;
@@ -1734,29 +1892,63 @@ int smu_v13_0_get_dpm_freq_by_index(struct smu_context *smu,
if (ret)
return ret;
- /*
- * BIT31: 0 - Fine grained DPM, 1 - Dicrete DPM
- * now, we un-support it
- */
*value = *value & 0x7fffffff;
return ret;
}
-int smu_v13_0_get_dpm_level_count(struct smu_context *smu,
- enum smu_clk_type clk_type,
- uint32_t *value)
+static int smu_v13_0_get_dpm_level_count(struct smu_context *smu,
+ enum smu_clk_type clk_type,
+ uint32_t *value)
{
int ret;
ret = smu_v13_0_get_dpm_freq_by_index(smu, clk_type, 0xff, value);
- /* FW returns 0 based max level, increment by one */
- if (!ret && value)
+ /* SMU v13.0.2 FW returns 0 based max level, increment by one for it */
+ if((smu->adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 2)) && (!ret && value))
++(*value);
return ret;
}
+static int smu_v13_0_get_fine_grained_status(struct smu_context *smu,
+ enum smu_clk_type clk_type,
+ bool *is_fine_grained_dpm)
+{
+ int ret = 0, clk_id = 0;
+ uint32_t param;
+ uint32_t value;
+
+ if (!is_fine_grained_dpm)
+ return -EINVAL;
+
+ if (!smu_cmn_clk_dpm_is_enabled(smu, clk_type))
+ return 0;
+
+ clk_id = smu_cmn_to_asic_specific_index(smu,
+ CMN2ASIC_MAPPING_CLK,
+ clk_type);
+ if (clk_id < 0)
+ return clk_id;
+
+ param = (uint32_t)(((clk_id & 0xffff) << 16) | 0xff);
+
+ ret = smu_cmn_send_smc_msg_with_param(smu,
+ SMU_MSG_GetDpmFreqByIndex,
+ param,
+ &value);
+ if (ret)
+ return ret;
+
+ /*
+ * BIT31: 1 - Fine grained DPM, 0 - Dicrete DPM
+ * now, we un-support it
+ */
+ *is_fine_grained_dpm = value & 0x80000000;
+
+ return 0;
+}
+
int smu_v13_0_set_single_dpm_table(struct smu_context *smu,
enum smu_clk_type clk_type,
struct smu_13_0_dpm_table *single_dpm_table)
@@ -1773,6 +1965,16 @@ int smu_v13_0_set_single_dpm_table(struct smu_context *smu,
return ret;
}
+ if (smu->adev->ip_versions[MP1_HWIP][0] != IP_VERSION(13, 0, 2)) {
+ ret = smu_v13_0_get_fine_grained_status(smu,
+ clk_type,
+ &single_dpm_table->is_fine_grained);
+ if (ret) {
+ dev_err(smu->adev->dev, "[%s] failed to get fine grained status!\n", __func__);
+ return ret;
+ }
+ }
+
for (i = 0; i < single_dpm_table->count; i++) {
ret = smu_v13_0_get_dpm_freq_by_index(smu,
clk_type,
@@ -1874,3 +2076,290 @@ int smu_v13_0_get_current_pcie_link_speed(struct smu_context *smu)
return link_speed[speed_level];
}
+int smu_v13_0_set_vcn_enable(struct smu_context *smu,
+ bool enable)
+{
+ struct amdgpu_device *adev = smu->adev;
+ int i, ret = 0;
+
+ for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
+ if (adev->vcn.harvest_config & (1 << i))
+ continue;
+
+ ret = smu_cmn_send_smc_msg_with_param(smu, enable ?
+ SMU_MSG_PowerUpVcn : SMU_MSG_PowerDownVcn,
+ i << 16U, NULL);
+ if (ret)
+ return ret;
+ }
+
+ return ret;
+}
+
+int smu_v13_0_set_jpeg_enable(struct smu_context *smu,
+ bool enable)
+{
+ return smu_cmn_send_smc_msg_with_param(smu, enable ?
+ SMU_MSG_PowerUpJpeg : SMU_MSG_PowerDownJpeg,
+ 0, NULL);
+}
+
+int smu_v13_0_run_btc(struct smu_context *smu)
+{
+ int res;
+
+ res = smu_cmn_send_smc_msg(smu, SMU_MSG_RunDcBtc, NULL);
+ if (res)
+ dev_err(smu->adev->dev, "RunDcBtc failed!\n");
+
+ return res;
+}
+
+int smu_v13_0_deep_sleep_control(struct smu_context *smu,
+ bool enablement)
+{
+ struct amdgpu_device *adev = smu->adev;
+ int ret = 0;
+
+ if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_DS_GFXCLK_BIT)) {
+ ret = smu_cmn_feature_set_enabled(smu, SMU_FEATURE_DS_GFXCLK_BIT, enablement);
+ if (ret) {
+ dev_err(adev->dev, "Failed to %s GFXCLK DS!\n", enablement ? "enable" : "disable");
+ return ret;
+ }
+ }
+
+ 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) {
+ dev_err(adev->dev, "Failed to %s SOCCLK DS!\n", enablement ? "enable" : "disable");
+ return ret;
+ }
+ }
+
+ if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_DS_LCLK_BIT)) {
+ ret = smu_cmn_feature_set_enabled(smu, SMU_FEATURE_DS_LCLK_BIT, enablement);
+ if (ret) {
+ dev_err(adev->dev, "Failed to %s LCLK DS!\n", enablement ? "enable" : "disable");
+ return ret;
+ }
+ }
+
+ if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_DS_VCN_BIT)) {
+ ret = smu_cmn_feature_set_enabled(smu, SMU_FEATURE_DS_VCN_BIT, enablement);
+ if (ret) {
+ dev_err(adev->dev, "Failed to %s VCN DS!\n", enablement ? "enable" : "disable");
+ return ret;
+ }
+ }
+
+ if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_DS_MP0CLK_BIT)) {
+ ret = smu_cmn_feature_set_enabled(smu, SMU_FEATURE_DS_MP0CLK_BIT, enablement);
+ if (ret) {
+ dev_err(adev->dev, "Failed to %s MP0/MPIOCLK DS!\n", enablement ? "enable" : "disable");
+ return ret;
+ }
+ }
+
+ if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_DS_MP1CLK_BIT)) {
+ ret = smu_cmn_feature_set_enabled(smu, SMU_FEATURE_DS_MP1CLK_BIT, enablement);
+ if (ret) {
+ dev_err(adev->dev, "Failed to %s MP1CLK DS!\n", enablement ? "enable" : "disable");
+ return ret;
+ }
+ }
+
+ return ret;
+}
+
+int smu_v13_0_gfx_ulv_control(struct smu_context *smu,
+ bool enablement)
+{
+ int ret = 0;
+
+ if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_GFX_ULV_BIT))
+ ret = smu_cmn_feature_set_enabled(smu, SMU_FEATURE_GFX_ULV_BIT, enablement);
+
+ return ret;
+}
+
+bool smu_v13_0_baco_is_support(struct smu_context *smu)
+{
+ struct smu_baco_context *smu_baco = &smu->smu_baco;
+
+ if (amdgpu_sriov_vf(smu->adev) ||
+ !smu_baco->platform_support)
+ return false;
+
+ if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_BACO_BIT) &&
+ !smu_cmn_feature_is_enabled(smu, SMU_FEATURE_BACO_BIT))
+ return false;
+
+ return true;
+}
+
+enum smu_baco_state smu_v13_0_baco_get_state(struct smu_context *smu)
+{
+ struct smu_baco_context *smu_baco = &smu->smu_baco;
+
+ return smu_baco->state;
+}
+
+int smu_v13_0_baco_set_state(struct smu_context *smu,
+ enum smu_baco_state state)
+{
+ struct smu_baco_context *smu_baco = &smu->smu_baco;
+ struct amdgpu_device *adev = smu->adev;
+ int ret = 0;
+
+ if (smu_v13_0_baco_get_state(smu) == state)
+ return 0;
+
+ if (state == SMU_BACO_STATE_ENTER) {
+ ret = smu_cmn_send_smc_msg_with_param(smu,
+ SMU_MSG_EnterBaco,
+ 0,
+ NULL);
+ } else {
+ ret = smu_cmn_send_smc_msg(smu,
+ SMU_MSG_ExitBaco,
+ NULL);
+ if (ret)
+ return ret;
+
+ /* clear vbios scratch 6 and 7 for coming asic reinit */
+ WREG32(adev->bios_scratch_reg_offset + 6, 0);
+ WREG32(adev->bios_scratch_reg_offset + 7, 0);
+ }
+
+ if (!ret)
+ smu_baco->state = state;
+
+ return ret;
+}
+
+int smu_v13_0_baco_enter(struct smu_context *smu)
+{
+ int ret = 0;
+
+ ret = smu_v13_0_baco_set_state(smu,
+ SMU_BACO_STATE_ENTER);
+ if (ret)
+ return ret;
+
+ msleep(10);
+
+ return ret;
+}
+
+int smu_v13_0_baco_exit(struct smu_context *smu)
+{
+ return smu_v13_0_baco_set_state(smu,
+ SMU_BACO_STATE_EXIT);
+}
+
+int smu_v13_0_od_edit_dpm_table(struct smu_context *smu,
+ enum PP_OD_DPM_TABLE_COMMAND type,
+ long input[], uint32_t size)
+{
+ struct smu_dpm_context *smu_dpm = &(smu->smu_dpm);
+ int ret = 0;
+
+ /* Only allowed in manual mode */
+ if (smu_dpm->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL)
+ return -EINVAL;
+
+ switch (type) {
+ case PP_OD_EDIT_SCLK_VDDC_TABLE:
+ if (size != 2) {
+ dev_err(smu->adev->dev, "Input parameter number not correct\n");
+ return -EINVAL;
+ }
+
+ if (input[0] == 0) {
+ if (input[1] < smu->gfx_default_hard_min_freq) {
+ dev_warn(smu->adev->dev,
+ "Fine grain setting minimum sclk (%ld) MHz is less than the minimum allowed (%d) MHz\n",
+ input[1], smu->gfx_default_hard_min_freq);
+ return -EINVAL;
+ }
+ smu->gfx_actual_hard_min_freq = input[1];
+ } else if (input[0] == 1) {
+ if (input[1] > smu->gfx_default_soft_max_freq) {
+ dev_warn(smu->adev->dev,
+ "Fine grain setting maximum sclk (%ld) MHz is greater than the maximum allowed (%d) MHz\n",
+ input[1], smu->gfx_default_soft_max_freq);
+ return -EINVAL;
+ }
+ smu->gfx_actual_soft_max_freq = input[1];
+ } else {
+ return -EINVAL;
+ }
+ break;
+ case PP_OD_RESTORE_DEFAULT_TABLE:
+ if (size != 0) {
+ dev_err(smu->adev->dev, "Input parameter number not correct\n");
+ return -EINVAL;
+ }
+ smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq;
+ smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq;
+ break;
+ case PP_OD_COMMIT_DPM_TABLE:
+ if (size != 0) {
+ dev_err(smu->adev->dev, "Input parameter number not correct\n");
+ return -EINVAL;
+ }
+ if (smu->gfx_actual_hard_min_freq > smu->gfx_actual_soft_max_freq) {
+ dev_err(smu->adev->dev,
+ "The setting minimum sclk (%d) MHz is greater than the setting maximum sclk (%d) MHz\n",
+ smu->gfx_actual_hard_min_freq,
+ smu->gfx_actual_soft_max_freq);
+ return -EINVAL;
+ }
+
+ ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinGfxClk,
+ smu->gfx_actual_hard_min_freq,
+ NULL);
+ if (ret) {
+ dev_err(smu->adev->dev, "Set hard min sclk failed!");
+ return ret;
+ }
+
+ ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk,
+ smu->gfx_actual_soft_max_freq,
+ NULL);
+ if (ret) {
+ dev_err(smu->adev->dev, "Set soft max sclk failed!");
+ return ret;
+ }
+ break;
+ default:
+ return -ENOSYS;
+ }
+
+ return ret;
+}
+
+int smu_v13_0_set_default_dpm_tables(struct smu_context *smu)
+{
+ struct smu_table_context *smu_table = &smu->smu_table;
+
+ return smu_cmn_update_table(smu, SMU_TABLE_DPMCLOCKS, 0,
+ smu_table->clocks_table, false);
+}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
new file mode 100644
index 000000000000..197a0e2ff063
--- /dev/null
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
@@ -0,0 +1,1648 @@
+/*
+ * Copyright 2021 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#define SWSMU_CODE_LAYER_L2
+
+#include <linux/firmware.h>
+#include <linux/pci.h>
+#include <linux/i2c.h>
+#include "amdgpu.h"
+#include "amdgpu_smu.h"
+#include "atomfirmware.h"
+#include "amdgpu_atomfirmware.h"
+#include "amdgpu_atombios.h"
+#include "smu_v13_0.h"
+#include "smu13_driver_if_v13_0_0.h"
+#include "soc15_common.h"
+#include "atom.h"
+#include "smu_v13_0_0_ppt.h"
+#include "smu_v13_0_0_pptable.h"
+#include "smu_v13_0_0_ppsmc.h"
+#include "nbio/nbio_4_3_0_offset.h"
+#include "nbio/nbio_4_3_0_sh_mask.h"
+#include "mp/mp_13_0_0_offset.h"
+#include "mp/mp_13_0_0_sh_mask.h"
+
+#include "asic_reg/mp/mp_13_0_0_sh_mask.h"
+#include "smu_cmn.h"
+#include "amdgpu_ras.h"
+
+/*
+ * DO NOT use these for err/warn/info/debug messages.
+ * Use dev_err, dev_warn, dev_info and dev_dbg instead.
+ * They are more MGPU friendly.
+ */
+#undef pr_err
+#undef pr_warn
+#undef pr_info
+#undef pr_debug
+
+#define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c))
+
+#define FEATURE_MASK(feature) (1ULL << feature)
+#define SMC_DPM_FEATURE ( \
+ FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT) | \
+ FEATURE_MASK(FEATURE_DPM_UCLK_BIT) | \
+ FEATURE_MASK(FEATURE_DPM_LINK_BIT) | \
+ FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT) | \
+ FEATURE_MASK(FEATURE_DPM_FCLK_BIT) | \
+ FEATURE_MASK(FEATURE_DPM_MP0CLK_BIT))
+
+#define MP0_MP1_DATA_REGION_SIZE_COMBOPPTABLE 0x4000
+
+static struct cmn2asic_msg_mapping smu_v13_0_0_message_map[SMU_MSG_MAX_COUNT] = {
+ MSG_MAP(TestMessage, PPSMC_MSG_TestMessage, 1),
+ MSG_MAP(GetSmuVersion, PPSMC_MSG_GetSmuVersion, 1),
+ MSG_MAP(GetDriverIfVersion, PPSMC_MSG_GetDriverIfVersion, 1),
+ MSG_MAP(SetAllowedFeaturesMaskLow, PPSMC_MSG_SetAllowedFeaturesMaskLow, 0),
+ MSG_MAP(SetAllowedFeaturesMaskHigh, PPSMC_MSG_SetAllowedFeaturesMaskHigh, 0),
+ MSG_MAP(EnableAllSmuFeatures, PPSMC_MSG_EnableAllSmuFeatures, 0),
+ MSG_MAP(DisableAllSmuFeatures, PPSMC_MSG_DisableAllSmuFeatures, 0),
+ MSG_MAP(EnableSmuFeaturesLow, PPSMC_MSG_EnableSmuFeaturesLow, 1),
+ MSG_MAP(EnableSmuFeaturesHigh, PPSMC_MSG_EnableSmuFeaturesHigh, 1),
+ MSG_MAP(DisableSmuFeaturesLow, PPSMC_MSG_DisableSmuFeaturesLow, 1),
+ MSG_MAP(DisableSmuFeaturesHigh, PPSMC_MSG_DisableSmuFeaturesHigh, 1),
+ MSG_MAP(GetEnabledSmuFeaturesLow, PPSMC_MSG_GetRunningSmuFeaturesLow, 1),
+ MSG_MAP(GetEnabledSmuFeaturesHigh, PPSMC_MSG_GetRunningSmuFeaturesHigh, 1),
+ MSG_MAP(SetWorkloadMask, PPSMC_MSG_SetWorkloadMask, 1),
+ MSG_MAP(SetPptLimit, PPSMC_MSG_SetPptLimit, 0),
+ MSG_MAP(SetDriverDramAddrHigh, PPSMC_MSG_SetDriverDramAddrHigh, 1),
+ MSG_MAP(SetDriverDramAddrLow, PPSMC_MSG_SetDriverDramAddrLow, 1),
+ MSG_MAP(SetToolsDramAddrHigh, PPSMC_MSG_SetToolsDramAddrHigh, 0),
+ MSG_MAP(SetToolsDramAddrLow, PPSMC_MSG_SetToolsDramAddrLow, 0),
+ MSG_MAP(TransferTableSmu2Dram, PPSMC_MSG_TransferTableSmu2Dram, 1),
+ MSG_MAP(TransferTableDram2Smu, PPSMC_MSG_TransferTableDram2Smu, 0),
+ MSG_MAP(UseDefaultPPTable, PPSMC_MSG_UseDefaultPPTable, 0),
+ MSG_MAP(RunDcBtc, PPSMC_MSG_RunDcBtc, 0),
+ MSG_MAP(EnterBaco, PPSMC_MSG_EnterBaco, 0),
+ MSG_MAP(ExitBaco, PPSMC_MSG_ExitBaco, 0),
+ MSG_MAP(SetSoftMinByFreq, PPSMC_MSG_SetSoftMinByFreq, 1),
+ MSG_MAP(SetSoftMaxByFreq, PPSMC_MSG_SetSoftMaxByFreq, 1),
+ MSG_MAP(SetHardMinByFreq, PPSMC_MSG_SetHardMinByFreq, 1),
+ MSG_MAP(SetHardMaxByFreq, PPSMC_MSG_SetHardMaxByFreq, 0),
+ MSG_MAP(GetMinDpmFreq, PPSMC_MSG_GetMinDpmFreq, 1),
+ MSG_MAP(GetMaxDpmFreq, PPSMC_MSG_GetMaxDpmFreq, 1),
+ MSG_MAP(GetDpmFreqByIndex, PPSMC_MSG_GetDpmFreqByIndex, 1),
+ MSG_MAP(PowerUpVcn, PPSMC_MSG_PowerUpVcn, 0),
+ MSG_MAP(PowerDownVcn, PPSMC_MSG_PowerDownVcn, 0),
+ MSG_MAP(PowerUpJpeg, PPSMC_MSG_PowerUpJpeg, 0),
+ MSG_MAP(PowerDownJpeg, PPSMC_MSG_PowerDownJpeg, 0),
+ MSG_MAP(GetDcModeMaxDpmFreq, PPSMC_MSG_GetDcModeMaxDpmFreq, 1),
+ MSG_MAP(OverridePcieParameters, PPSMC_MSG_OverridePcieParameters, 0),
+ MSG_MAP(DramLogSetDramAddrHigh, PPSMC_MSG_DramLogSetDramAddrHigh, 0),
+ MSG_MAP(DramLogSetDramAddrLow, PPSMC_MSG_DramLogSetDramAddrLow, 0),
+ MSG_MAP(DramLogSetDramSize, PPSMC_MSG_DramLogSetDramSize, 0),
+ MSG_MAP(AllowGfxOff, PPSMC_MSG_AllowGfxOff, 0),
+ MSG_MAP(DisallowGfxOff, PPSMC_MSG_DisallowGfxOff, 0),
+ MSG_MAP(SetMGpuFanBoostLimitRpm, PPSMC_MSG_SetMGpuFanBoostLimitRpm, 0),
+ MSG_MAP(GetPptLimit, PPSMC_MSG_GetPptLimit, 0),
+ MSG_MAP(NotifyPowerSource, PPSMC_MSG_NotifyPowerSource, 0),
+};
+
+static struct cmn2asic_mapping smu_v13_0_0_clk_map[SMU_CLK_COUNT] = {
+ CLK_MAP(GFXCLK, PPCLK_GFXCLK),
+ CLK_MAP(SCLK, PPCLK_GFXCLK),
+ CLK_MAP(SOCCLK, PPCLK_SOCCLK),
+ CLK_MAP(FCLK, PPCLK_FCLK),
+ CLK_MAP(UCLK, PPCLK_UCLK),
+ CLK_MAP(MCLK, PPCLK_UCLK),
+ CLK_MAP(VCLK, PPCLK_VCLK_0),
+ CLK_MAP(VCLK1, PPCLK_VCLK_1),
+ CLK_MAP(DCLK, PPCLK_DCLK_0),
+ CLK_MAP(DCLK1, PPCLK_DCLK_1),
+};
+
+static struct cmn2asic_mapping smu_v13_0_0_feature_mask_map[SMU_FEATURE_COUNT] = {
+ FEA_MAP(FW_DATA_READ),
+ FEA_MAP(DPM_GFXCLK),
+ FEA_MAP(DPM_GFX_POWER_OPTIMIZER),
+ FEA_MAP(DPM_UCLK),
+ FEA_MAP(DPM_FCLK),
+ FEA_MAP(DPM_SOCCLK),
+ FEA_MAP(DPM_MP0CLK),
+ FEA_MAP(DPM_LINK),
+ FEA_MAP(DPM_DCN),
+ FEA_MAP(VMEMP_SCALING),
+ FEA_MAP(VDDIO_MEM_SCALING),
+ FEA_MAP(DS_GFXCLK),
+ FEA_MAP(DS_SOCCLK),
+ FEA_MAP(DS_FCLK),
+ FEA_MAP(DS_LCLK),
+ FEA_MAP(DS_DCFCLK),
+ FEA_MAP(DS_UCLK),
+ FEA_MAP(GFX_ULV),
+ FEA_MAP(FW_DSTATE),
+ FEA_MAP(GFXOFF),
+ FEA_MAP(BACO),
+ FEA_MAP(MM_DPM),
+ FEA_MAP(SOC_MPCLK_DS),
+ FEA_MAP(BACO_MPCLK_DS),
+ FEA_MAP(THROTTLERS),
+ FEA_MAP(SMARTSHIFT),
+ FEA_MAP(GTHR),
+ FEA_MAP(ACDC),
+ FEA_MAP(VR0HOT),
+ FEA_MAP(FW_CTF),
+ FEA_MAP(FAN_CONTROL),
+ FEA_MAP(GFX_DCS),
+ FEA_MAP(GFX_READ_MARGIN),
+ FEA_MAP(LED_DISPLAY),
+ FEA_MAP(GFXCLK_SPREAD_SPECTRUM),
+ FEA_MAP(OUT_OF_BAND_MONITOR),
+ FEA_MAP(OPTIMIZED_VMIN),
+ FEA_MAP(GFX_IMU),
+ FEA_MAP(BOOT_TIME_CAL),
+ FEA_MAP(GFX_PCC_DFLL),
+ FEA_MAP(SOC_CG),
+ FEA_MAP(DF_CSTATE),
+ FEA_MAP(GFX_EDC),
+ FEA_MAP(BOOT_POWER_OPT),
+ FEA_MAP(CLOCK_POWER_DOWN_BYPASS),
+ FEA_MAP(DS_VCN),
+ FEA_MAP(BACO_CG),
+ FEA_MAP(MEM_TEMP_READ),
+ FEA_MAP(ATHUB_MMHUB_PG),
+ FEA_MAP(SOC_PCC),
+};
+
+static struct cmn2asic_mapping smu_v13_0_0_table_map[SMU_TABLE_COUNT] = {
+ TAB_MAP(PPTABLE),
+ TAB_MAP(WATERMARKS),
+ TAB_MAP(AVFS_PSM_DEBUG),
+ TAB_MAP(PMSTATUSLOG),
+ TAB_MAP(SMU_METRICS),
+ TAB_MAP(DRIVER_SMU_CONFIG),
+ TAB_MAP(ACTIVITY_MONITOR_COEFF),
+ [SMU_TABLE_COMBO_PPTABLE] = {1, TABLE_COMBO_PPTABLE},
+};
+
+static struct cmn2asic_mapping smu_v13_0_0_pwr_src_map[SMU_POWER_SOURCE_COUNT] = {
+ PWR_MAP(AC),
+ PWR_MAP(DC),
+};
+
+static struct cmn2asic_mapping smu_v13_0_0_workload_map[PP_SMC_POWER_PROFILE_COUNT] = {
+ WORKLOAD_MAP(PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT, WORKLOAD_PPLIB_DEFAULT_BIT),
+ WORKLOAD_MAP(PP_SMC_POWER_PROFILE_FULLSCREEN3D, WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT),
+ WORKLOAD_MAP(PP_SMC_POWER_PROFILE_POWERSAVING, WORKLOAD_PPLIB_POWER_SAVING_BIT),
+ WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VIDEO, WORKLOAD_PPLIB_VIDEO_BIT),
+ WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VR, WORKLOAD_PPLIB_VR_BIT),
+ WORKLOAD_MAP(PP_SMC_POWER_PROFILE_COMPUTE, WORKLOAD_PPLIB_COMPUTE_BIT),
+ WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CUSTOM, WORKLOAD_PPLIB_CUSTOM_BIT),
+};
+
+static const uint8_t smu_v13_0_0_throttler_map[] = {
+ [THROTTLER_PPT0_BIT] = (SMU_THROTTLER_PPT0_BIT),
+ [THROTTLER_PPT1_BIT] = (SMU_THROTTLER_PPT1_BIT),
+ [THROTTLER_PPT2_BIT] = (SMU_THROTTLER_PPT2_BIT),
+ [THROTTLER_PPT3_BIT] = (SMU_THROTTLER_PPT3_BIT),
+ [THROTTLER_TDC_GFX_BIT] = (SMU_THROTTLER_TDC_GFX_BIT),
+ [THROTTLER_TDC_SOC_BIT] = (SMU_THROTTLER_TDC_SOC_BIT),
+ [THROTTLER_TEMP_EDGE_BIT] = (SMU_THROTTLER_TEMP_EDGE_BIT),
+ [THROTTLER_TEMP_HOTSPOT_BIT] = (SMU_THROTTLER_TEMP_HOTSPOT_BIT),
+ [THROTTLER_TEMP_MEM_BIT] = (SMU_THROTTLER_TEMP_MEM_BIT),
+ [THROTTLER_TEMP_VR_GFX_BIT] = (SMU_THROTTLER_TEMP_VR_GFX_BIT),
+ [THROTTLER_TEMP_VR_SOC_BIT] = (SMU_THROTTLER_TEMP_VR_SOC_BIT),
+ [THROTTLER_TEMP_VR_MEM0_BIT] = (SMU_THROTTLER_TEMP_VR_MEM0_BIT),
+ [THROTTLER_TEMP_VR_MEM1_BIT] = (SMU_THROTTLER_TEMP_VR_MEM1_BIT),
+ [THROTTLER_TEMP_LIQUID0_BIT] = (SMU_THROTTLER_TEMP_LIQUID0_BIT),
+ [THROTTLER_TEMP_LIQUID1_BIT] = (SMU_THROTTLER_TEMP_LIQUID1_BIT),
+ [THROTTLER_GFX_APCC_PLUS_BIT] = (SMU_THROTTLER_APCC_BIT),
+ [THROTTLER_FIT_BIT] = (SMU_THROTTLER_FIT_BIT),
+};
+
+static int
+smu_v13_0_0_get_allowed_feature_mask(struct smu_context *smu,
+ uint32_t *feature_mask, uint32_t num)
+{
+ struct amdgpu_device *adev = smu->adev;
+
+ if (num > 2)
+ return -EINVAL;
+
+ memset(feature_mask, 0, sizeof(uint32_t) * num);
+
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_FW_DATA_READ_BIT);
+
+ if (adev->pm.pp_feature & PP_SCLK_DPM_MASK) {
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT);
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_GFX_IMU_BIT);
+ }
+
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_MM_DPM_BIT);
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DS_VCN_BIT);
+
+ if ((adev->pg_flags & AMD_PG_SUPPORT_ATHUB) &&
+ (adev->pg_flags & AMD_PG_SUPPORT_MMHUB))
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_ATHUB_MMHUB_PG_BIT);
+
+ if (adev->pm.pp_feature & PP_SOCCLK_DPM_MASK)
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT);
+
+#if 0
+ if (adev->pm.pp_feature & PP_GFXOFF_MASK)
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_GFXOFF_BIT);
+#endif
+
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_THROTTLERS_BIT);
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_FAN_CONTROL_BIT);
+
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DF_CSTATE_BIT);
+
+ if (adev->pm.pp_feature & PP_MCLK_DPM_MASK) {
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_UCLK_BIT);
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_VMEMP_SCALING_BIT);
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_VDDIO_MEM_SCALING_BIT);
+ }
+
+#if 0
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_MEM_TEMP_READ_BIT);
+#endif
+
+ if (adev->pm.pp_feature & PP_SCLK_DEEP_SLEEP_MASK)
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DS_GFXCLK_BIT);
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DS_SOCCLK_BIT);
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_SOC_MPCLK_DS_BIT);
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_BACO_MPCLK_DS_BIT);
+
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_FCLK_BIT);
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_DCN_BIT);
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DS_DCFCLK_BIT);
+
+ if (adev->pm.pp_feature & PP_PCIE_DPM_MASK) {
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_LINK_BIT);
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DS_LCLK_BIT);
+ }
+
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_BACO_BIT);
+
+ return 0;
+}
+
+static int smu_v13_0_0_check_powerplay_table(struct smu_context *smu)
+{
+ struct smu_table_context *table_context = &smu->smu_table;
+ struct smu_13_0_0_powerplay_table *powerplay_table =
+ table_context->power_play_table;
+ struct smu_baco_context *smu_baco = &smu->smu_baco;
+
+ if (powerplay_table->platform_caps & SMU_13_0_0_PP_PLATFORM_CAP_HARDWAREDC)
+ smu->dc_controlled_by_gpio = true;
+
+ if (powerplay_table->platform_caps & SMU_13_0_0_PP_PLATFORM_CAP_BACO ||
+ powerplay_table->platform_caps & SMU_13_0_0_PP_PLATFORM_CAP_MACO)
+ smu_baco->platform_support = true;
+
+ table_context->thermal_controller_type =
+ powerplay_table->thermal_controller_type;
+
+ /*
+ * Instead of having its own buffer space and get overdrive_table copied,
+ * smu->od_settings just points to the actual overdrive_table
+ */
+ smu->od_settings = &powerplay_table->overdrive_table;
+
+ return 0;
+}
+
+static int smu_v13_0_0_store_powerplay_table(struct smu_context *smu)
+{
+ struct smu_table_context *table_context = &smu->smu_table;
+ struct smu_13_0_0_powerplay_table *powerplay_table =
+ table_context->power_play_table;
+
+ memcpy(table_context->driver_pptable, &powerplay_table->smc_pptable,
+ sizeof(PPTable_t));
+
+ return 0;
+}
+
+#ifndef atom_smc_dpm_info_table_13_0_0
+struct atom_smc_dpm_info_table_13_0_0 {
+ struct atom_common_table_header table_header;
+ BoardTable_t BoardTable;
+};
+#endif
+
+static int smu_v13_0_0_append_powerplay_table(struct smu_context *smu)
+{
+ struct smu_table_context *table_context = &smu->smu_table;
+ PPTable_t *smc_pptable = table_context->driver_pptable;
+ struct atom_smc_dpm_info_table_13_0_0 *smc_dpm_table;
+ BoardTable_t *BoardTable = &smc_pptable->BoardTable;
+ int index, ret;
+
+ index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
+ smc_dpm_info);
+
+ ret = amdgpu_atombios_get_data_table(smu->adev, index, NULL, NULL, NULL,
+ (uint8_t **)&smc_dpm_table);
+ if (ret)
+ return ret;
+
+ memcpy(BoardTable, &smc_dpm_table->BoardTable, sizeof(BoardTable_t));
+
+ return 0;
+}
+
+static int smu_v13_0_0_setup_pptable(struct smu_context *smu)
+{
+ struct smu_table_context *smu_table = &smu->smu_table;
+ void *combo_pptable = smu_table->combo_pptable;
+ struct amdgpu_device *adev = smu->adev;
+ int ret = 0;
+
+ /*
+ * With SCPM enabled, the pptable used will be signed. It cannot
+ * be used directly by driver. To get the raw pptable, we need to
+ * rely on the combo pptable(and its revelant SMU message).
+ */
+ if (adev->scpm_enabled) {
+ ret = smu_cmn_get_combo_pptable(smu);
+ if (ret)
+ return ret;
+
+ smu->smu_table.power_play_table = combo_pptable;
+ smu->smu_table.power_play_table_size = sizeof(struct smu_13_0_0_powerplay_table);
+ } else {
+ ret = smu_v13_0_setup_pptable(smu);
+ if (ret)
+ return ret;
+ }
+
+ ret = smu_v13_0_0_store_powerplay_table(smu);
+ if (ret)
+ return ret;
+
+ /*
+ * With SCPM enabled, the operation below will be handled
+ * by PSP. Driver involvment is unnecessary and useless.
+ */
+ if (!adev->scpm_enabled) {
+ ret = smu_v13_0_0_append_powerplay_table(smu);
+ if (ret)
+ return ret;
+ }
+
+ ret = smu_v13_0_0_check_powerplay_table(smu);
+ if (ret)
+ return ret;
+
+ return ret;
+}
+
+static int smu_v13_0_0_tables_init(struct smu_context *smu)
+{
+ struct smu_table_context *smu_table = &smu->smu_table;
+ struct smu_table *tables = smu_table->tables;
+
+ SMU_TABLE_INIT(tables, SMU_TABLE_PPTABLE, sizeof(PPTable_t),
+ PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
+ SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, sizeof(Watermarks_t),
+ PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
+ SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetricsExternal_t),
+ PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
+ SMU_TABLE_INIT(tables, SMU_TABLE_I2C_COMMANDS, sizeof(SwI2cRequest_t),
+ PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
+ SMU_TABLE_INIT(tables, SMU_TABLE_OVERDRIVE, sizeof(OverDriveTable_t),
+ PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
+ SMU_TABLE_INIT(tables, SMU_TABLE_PMSTATUSLOG, SMU13_TOOL_SIZE,
+ PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
+ SMU_TABLE_INIT(tables, SMU_TABLE_ACTIVITY_MONITOR_COEFF,
+ sizeof(DpmActivityMonitorCoeffIntExternal_t), PAGE_SIZE,
+ AMDGPU_GEM_DOMAIN_VRAM);
+ SMU_TABLE_INIT(tables, SMU_TABLE_COMBO_PPTABLE, MP0_MP1_DATA_REGION_SIZE_COMBOPPTABLE,
+ PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
+
+ smu_table->metrics_table = kzalloc(sizeof(SmuMetricsExternal_t), GFP_KERNEL);
+ if (!smu_table->metrics_table)
+ goto err0_out;
+ smu_table->metrics_time = 0;
+
+ smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v1_3);
+ smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL);
+ if (!smu_table->gpu_metrics_table)
+ goto err1_out;
+
+ smu_table->watermarks_table = kzalloc(sizeof(Watermarks_t), GFP_KERNEL);
+ if (!smu_table->watermarks_table)
+ goto err2_out;
+
+ return 0;
+
+err2_out:
+ kfree(smu_table->gpu_metrics_table);
+err1_out:
+ kfree(smu_table->metrics_table);
+err0_out:
+ return -ENOMEM;
+}
+
+static int smu_v13_0_0_allocate_dpm_context(struct smu_context *smu)
+{
+ struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
+
+ smu_dpm->dpm_context = kzalloc(sizeof(struct smu_13_0_dpm_context),
+ GFP_KERNEL);
+ if (!smu_dpm->dpm_context)
+ return -ENOMEM;
+
+ smu_dpm->dpm_context_size = sizeof(struct smu_13_0_dpm_context);
+
+ return 0;
+}
+
+static int smu_v13_0_0_init_smc_tables(struct smu_context *smu)
+{
+ int ret = 0;
+
+ ret = smu_v13_0_0_tables_init(smu);
+ if (ret)
+ return ret;
+
+ ret = smu_v13_0_0_allocate_dpm_context(smu);
+ if (ret)
+ return ret;
+
+ return smu_v13_0_init_smc_tables(smu);
+}
+
+static int smu_v13_0_0_set_default_dpm_table(struct smu_context *smu)
+{
+ struct smu_13_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context;
+ struct smu_table_context *table_context = &smu->smu_table;
+ PPTable_t *pptable = table_context->driver_pptable;
+ SkuTable_t *skutable = &pptable->SkuTable;
+ struct smu_13_0_dpm_table *dpm_table;
+ struct smu_13_0_pcie_table *pcie_table;
+ uint32_t link_level;
+ int ret = 0;
+
+ /* socclk dpm table setup */
+ dpm_table = &dpm_context->dpm_tables.soc_table;
+ if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) {
+ ret = smu_v13_0_set_single_dpm_table(smu,
+ SMU_SOCCLK,
+ dpm_table);
+ if (ret)
+ return ret;
+ } else {
+ dpm_table->count = 1;
+ dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.socclk / 100;
+ dpm_table->dpm_levels[0].enabled = true;
+ dpm_table->min = dpm_table->dpm_levels[0].value;
+ dpm_table->max = dpm_table->dpm_levels[0].value;
+ }
+
+ /* gfxclk dpm table setup */
+ dpm_table = &dpm_context->dpm_tables.gfx_table;
+ if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT)) {
+ ret = smu_v13_0_set_single_dpm_table(smu,
+ SMU_GFXCLK,
+ dpm_table);
+ if (ret)
+ return ret;
+ } else {
+ dpm_table->count = 1;
+ dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100;
+ dpm_table->dpm_levels[0].enabled = true;
+ dpm_table->min = dpm_table->dpm_levels[0].value;
+ dpm_table->max = dpm_table->dpm_levels[0].value;
+ }
+
+ /* uclk dpm table setup */
+ dpm_table = &dpm_context->dpm_tables.uclk_table;
+ if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) {
+ ret = smu_v13_0_set_single_dpm_table(smu,
+ SMU_UCLK,
+ dpm_table);
+ if (ret)
+ return ret;
+ } else {
+ dpm_table->count = 1;
+ dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.uclk / 100;
+ dpm_table->dpm_levels[0].enabled = true;
+ dpm_table->min = dpm_table->dpm_levels[0].value;
+ dpm_table->max = dpm_table->dpm_levels[0].value;
+ }
+
+ /* fclk dpm table setup */
+ dpm_table = &dpm_context->dpm_tables.fclk_table;
+ if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_FCLK_BIT)) {
+ ret = smu_v13_0_set_single_dpm_table(smu,
+ SMU_FCLK,
+ dpm_table);
+ if (ret)
+ return ret;
+ } else {
+ dpm_table->count = 1;
+ dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.fclk / 100;
+ dpm_table->dpm_levels[0].enabled = true;
+ dpm_table->min = dpm_table->dpm_levels[0].value;
+ dpm_table->max = dpm_table->dpm_levels[0].value;
+ }
+
+ /* vclk dpm table setup */
+ dpm_table = &dpm_context->dpm_tables.vclk_table;
+ if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_VCLK_BIT)) {
+ ret = smu_v13_0_set_single_dpm_table(smu,
+ SMU_VCLK,
+ dpm_table);
+ if (ret)
+ return ret;
+ } else {
+ dpm_table->count = 1;
+ dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.vclk / 100;
+ dpm_table->dpm_levels[0].enabled = true;
+ dpm_table->min = dpm_table->dpm_levels[0].value;
+ dpm_table->max = dpm_table->dpm_levels[0].value;
+ }
+
+ /* dclk dpm table setup */
+ dpm_table = &dpm_context->dpm_tables.dclk_table;
+ if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_DCLK_BIT)) {
+ ret = smu_v13_0_set_single_dpm_table(smu,
+ SMU_DCLK,
+ dpm_table);
+ if (ret)
+ return ret;
+ } else {
+ dpm_table->count = 1;
+ dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dclk / 100;
+ dpm_table->dpm_levels[0].enabled = true;
+ dpm_table->min = dpm_table->dpm_levels[0].value;
+ dpm_table->max = dpm_table->dpm_levels[0].value;
+ }
+
+ /* lclk dpm table setup */
+ pcie_table = &dpm_context->dpm_tables.pcie_table;
+ pcie_table->num_of_link_levels = 0;
+ for (link_level = 0; link_level < NUM_LINK_LEVELS; link_level++) {
+ if (!skutable->PcieGenSpeed[link_level] &&
+ !skutable->PcieLaneCount[link_level] &&
+ !skutable->LclkFreq[link_level])
+ continue;
+
+ pcie_table->pcie_gen[pcie_table->num_of_link_levels] =
+ skutable->PcieGenSpeed[link_level];
+ pcie_table->pcie_lane[pcie_table->num_of_link_levels] =
+ skutable->PcieLaneCount[link_level];
+ pcie_table->clk_freq[pcie_table->num_of_link_levels] =
+ skutable->LclkFreq[link_level];
+ pcie_table->num_of_link_levels++;
+ }
+
+ return 0;
+}
+
+static bool smu_v13_0_0_is_dpm_running(struct smu_context *smu)
+{
+ int ret = 0;
+ uint64_t feature_enabled;
+
+ ret = smu_cmn_get_enabled_mask(smu, &feature_enabled);
+ if (ret)
+ return false;
+
+ return !!(feature_enabled & SMC_DPM_FEATURE);
+}
+
+static void smu_v13_0_0_dump_pptable(struct smu_context *smu)
+{
+ struct smu_table_context *table_context = &smu->smu_table;
+ PPTable_t *pptable = table_context->driver_pptable;
+ SkuTable_t *skutable = &pptable->SkuTable;
+
+ dev_info(smu->adev->dev, "Dumped PPTable:\n");
+
+ dev_info(smu->adev->dev, "Version = 0x%08x\n", skutable->Version);
+ dev_info(smu->adev->dev, "FeaturesToRun[0] = 0x%08x\n", skutable->FeaturesToRun[0]);
+ dev_info(smu->adev->dev, "FeaturesToRun[1] = 0x%08x\n", skutable->FeaturesToRun[1]);
+}
+
+static int smu_v13_0_0_system_features_control(struct smu_context *smu,
+ bool en)
+{
+ return smu_v13_0_system_features_control(smu, en);
+}
+
+static uint32_t smu_v13_0_get_throttler_status(SmuMetrics_t *metrics)
+{
+ uint32_t throttler_status = 0;
+ int i;
+
+ for (i = 0; i < THROTTLER_COUNT; i++)
+ throttler_status |=
+ (metrics->ThrottlingPercentage[i] ? 1U << i : 0);
+
+ return throttler_status;
+}
+
+#define SMU_13_0_0_BUSY_THRESHOLD 15
+static int smu_v13_0_0_get_smu_metrics_data(struct smu_context *smu,
+ MetricsMember_t member,
+ uint32_t *value)
+{
+ struct smu_table_context *smu_table = &smu->smu_table;
+ SmuMetrics_t *metrics =
+ &(((SmuMetricsExternal_t *)(smu_table->metrics_table))->SmuMetrics);
+ int ret = 0;
+
+ ret = smu_cmn_get_metrics_table(smu,
+ NULL,
+ false);
+ if (ret)
+ return ret;
+
+ switch (member) {
+ case METRICS_CURR_GFXCLK:
+ *value = metrics->CurrClock[PPCLK_GFXCLK];
+ break;
+ case METRICS_CURR_SOCCLK:
+ *value = metrics->CurrClock[PPCLK_SOCCLK];
+ break;
+ case METRICS_CURR_UCLK:
+ *value = metrics->CurrClock[PPCLK_UCLK];
+ break;
+ case METRICS_CURR_VCLK:
+ *value = metrics->CurrClock[PPCLK_VCLK_0];
+ break;
+ case METRICS_CURR_VCLK1:
+ *value = metrics->CurrClock[PPCLK_VCLK_1];
+ break;
+ case METRICS_CURR_DCLK:
+ *value = metrics->CurrClock[PPCLK_DCLK_0];
+ break;
+ case METRICS_CURR_DCLK1:
+ *value = metrics->CurrClock[PPCLK_DCLK_1];
+ break;
+ case METRICS_CURR_FCLK:
+ *value = metrics->CurrClock[PPCLK_FCLK];
+ break;
+ case METRICS_AVERAGE_GFXCLK:
+ if (metrics->AverageGfxActivity <= SMU_13_0_0_BUSY_THRESHOLD)
+ *value = metrics->AverageGfxclkFrequencyPostDs;
+ else
+ *value = metrics->AverageGfxclkFrequencyPreDs;
+ break;
+ case METRICS_AVERAGE_FCLK:
+ if (metrics->AverageUclkActivity <= SMU_13_0_0_BUSY_THRESHOLD)
+ *value = metrics->AverageFclkFrequencyPostDs;
+ else
+ *value = metrics->AverageFclkFrequencyPreDs;
+ break;
+ case METRICS_AVERAGE_UCLK:
+ if (metrics->AverageUclkActivity <= SMU_13_0_0_BUSY_THRESHOLD)
+ *value = metrics->AverageMemclkFrequencyPostDs;
+ else
+ *value = metrics->AverageMemclkFrequencyPreDs;
+ break;
+ case METRICS_AVERAGE_VCLK:
+ *value = metrics->AverageVclk0Frequency;
+ break;
+ case METRICS_AVERAGE_DCLK:
+ *value = metrics->AverageDclk0Frequency;
+ break;
+ case METRICS_AVERAGE_VCLK1:
+ *value = metrics->AverageVclk1Frequency;
+ break;
+ case METRICS_AVERAGE_DCLK1:
+ *value = metrics->AverageDclk1Frequency;
+ break;
+ case METRICS_AVERAGE_GFXACTIVITY:
+ *value = metrics->AverageGfxActivity;
+ break;
+ case METRICS_AVERAGE_MEMACTIVITY:
+ *value = metrics->AverageUclkActivity;
+ break;
+ case METRICS_AVERAGE_SOCKETPOWER:
+ *value = metrics->AverageSocketPower << 8;
+ break;
+ case METRICS_TEMPERATURE_EDGE:
+ *value = metrics->AvgTemperature[TEMP_EDGE] *
+ SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ break;
+ case METRICS_TEMPERATURE_HOTSPOT:
+ *value = metrics->AvgTemperature[TEMP_HOTSPOT] *
+ SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ break;
+ case METRICS_TEMPERATURE_MEM:
+ *value = metrics->AvgTemperature[TEMP_MEM] *
+ SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ break;
+ case METRICS_TEMPERATURE_VRGFX:
+ *value = metrics->AvgTemperature[TEMP_VR_GFX] *
+ SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ break;
+ case METRICS_TEMPERATURE_VRSOC:
+ *value = metrics->AvgTemperature[TEMP_VR_SOC] *
+ SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ break;
+ case METRICS_THROTTLER_STATUS:
+ *value = smu_v13_0_get_throttler_status(metrics);
+ break;
+ case METRICS_CURR_FANSPEED:
+ *value = metrics->AvgFanRpm;
+ break;
+ case METRICS_CURR_FANPWM:
+ *value = metrics->AvgFanPwm;
+ break;
+ case METRICS_VOLTAGE_VDDGFX:
+ *value = metrics->AvgVoltage[SVI_PLANE_GFX];
+ break;
+ case METRICS_PCIE_RATE:
+ *value = metrics->PcieRate;
+ break;
+ case METRICS_PCIE_WIDTH:
+ *value = metrics->PcieWidth;
+ break;
+ default:
+ *value = UINT_MAX;
+ break;
+ }
+
+ return ret;
+}
+
+static int smu_v13_0_0_read_sensor(struct smu_context *smu,
+ enum amd_pp_sensors sensor,
+ void *data,
+ uint32_t *size)
+{
+ struct smu_table_context *table_context = &smu->smu_table;
+ PPTable_t *smc_pptable = table_context->driver_pptable;
+ int ret = 0;
+
+ switch (sensor) {
+ case AMDGPU_PP_SENSOR_MAX_FAN_RPM:
+ *(uint16_t *)data = smc_pptable->SkuTable.FanMaximumRpm;
+ *size = 4;
+ break;
+ case AMDGPU_PP_SENSOR_MEM_LOAD:
+ ret = smu_v13_0_0_get_smu_metrics_data(smu,
+ METRICS_AVERAGE_MEMACTIVITY,
+ (uint32_t *)data);
+ *size = 4;
+ break;
+ case AMDGPU_PP_SENSOR_GPU_LOAD:
+ ret = smu_v13_0_0_get_smu_metrics_data(smu,
+ METRICS_AVERAGE_GFXACTIVITY,
+ (uint32_t *)data);
+ *size = 4;
+ break;
+ case AMDGPU_PP_SENSOR_GPU_POWER:
+ ret = smu_v13_0_0_get_smu_metrics_data(smu,
+ METRICS_AVERAGE_SOCKETPOWER,
+ (uint32_t *)data);
+ *size = 4;
+ break;
+ case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
+ ret = smu_v13_0_0_get_smu_metrics_data(smu,
+ METRICS_TEMPERATURE_HOTSPOT,
+ (uint32_t *)data);
+ *size = 4;
+ break;
+ case AMDGPU_PP_SENSOR_EDGE_TEMP:
+ ret = smu_v13_0_0_get_smu_metrics_data(smu,
+ METRICS_TEMPERATURE_EDGE,
+ (uint32_t *)data);
+ *size = 4;
+ break;
+ case AMDGPU_PP_SENSOR_MEM_TEMP:
+ ret = smu_v13_0_0_get_smu_metrics_data(smu,
+ METRICS_TEMPERATURE_MEM,
+ (uint32_t *)data);
+ *size = 4;
+ break;
+ case AMDGPU_PP_SENSOR_GFX_MCLK:
+ ret = smu_v13_0_0_get_smu_metrics_data(smu,
+ METRICS_AVERAGE_UCLK,
+ (uint32_t *)data);
+ *(uint32_t *)data *= 100;
+ *size = 4;
+ break;
+ case AMDGPU_PP_SENSOR_GFX_SCLK:
+ ret = smu_v13_0_0_get_smu_metrics_data(smu,
+ METRICS_AVERAGE_GFXCLK,
+ (uint32_t *)data);
+ *(uint32_t *)data *= 100;
+ *size = 4;
+ break;
+ case AMDGPU_PP_SENSOR_VDDGFX:
+ ret = smu_v13_0_0_get_smu_metrics_data(smu,
+ METRICS_VOLTAGE_VDDGFX,
+ (uint32_t *)data);
+ *size = 4;
+ break;
+ default:
+ ret = -EOPNOTSUPP;
+ break;
+ }
+
+ return ret;
+}
+
+static int smu_v13_0_0_get_current_clk_freq_by_table(struct smu_context *smu,
+ enum smu_clk_type clk_type,
+ uint32_t *value)
+{
+ MetricsMember_t member_type;
+ int clk_id = 0;
+
+ clk_id = smu_cmn_to_asic_specific_index(smu,
+ CMN2ASIC_MAPPING_CLK,
+ clk_type);
+ if (clk_id < 0)
+ return -EINVAL;
+
+ switch (clk_id) {
+ case PPCLK_GFXCLK:
+ member_type = METRICS_AVERAGE_GFXCLK;
+ break;
+ case PPCLK_UCLK:
+ member_type = METRICS_CURR_UCLK;
+ break;
+ case PPCLK_FCLK:
+ member_type = METRICS_CURR_FCLK;
+ break;
+ case PPCLK_SOCCLK:
+ member_type = METRICS_CURR_SOCCLK;
+ break;
+ case PPCLK_VCLK_0:
+ member_type = METRICS_AVERAGE_VCLK;
+ break;
+ case PPCLK_DCLK_0:
+ member_type = METRICS_AVERAGE_DCLK;
+ break;
+ case PPCLK_VCLK_1:
+ member_type = METRICS_AVERAGE_VCLK1;
+ break;
+ case PPCLK_DCLK_1:
+ member_type = METRICS_AVERAGE_DCLK1;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return smu_v13_0_0_get_smu_metrics_data(smu,
+ member_type,
+ value);
+}
+
+static int smu_v13_0_0_print_clk_levels(struct smu_context *smu,
+ enum smu_clk_type clk_type,
+ char *buf)
+{
+ struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
+ struct smu_13_0_dpm_context *dpm_context = smu_dpm->dpm_context;
+ struct smu_13_0_dpm_table *single_dpm_table;
+ struct smu_13_0_pcie_table *pcie_table;
+ const int link_width[] = {0, 1, 2, 4, 8, 12, 16};
+ uint32_t gen_speed, lane_width;
+ int i, curr_freq, size = 0;
+ int ret = 0;
+
+ smu_cmn_get_sysfs_buf(&buf, &size);
+
+ if (amdgpu_ras_intr_triggered()) {
+ size += sysfs_emit_at(buf, size, "unavailable\n");
+ return size;
+ }
+
+ switch (clk_type) {
+ case SMU_SCLK:
+ single_dpm_table = &(dpm_context->dpm_tables.gfx_table);
+ break;
+ case SMU_MCLK:
+ single_dpm_table = &(dpm_context->dpm_tables.uclk_table);
+ break;
+ case SMU_SOCCLK:
+ single_dpm_table = &(dpm_context->dpm_tables.soc_table);
+ break;
+ case SMU_FCLK:
+ single_dpm_table = &(dpm_context->dpm_tables.fclk_table);
+ break;
+ case SMU_VCLK:
+ case SMU_VCLK1:
+ single_dpm_table = &(dpm_context->dpm_tables.vclk_table);
+ break;
+ case SMU_DCLK:
+ case SMU_DCLK1:
+ single_dpm_table = &(dpm_context->dpm_tables.dclk_table);
+ break;
+ default:
+ break;
+ }
+
+ switch (clk_type) {
+ case SMU_SCLK:
+ case SMU_MCLK:
+ case SMU_SOCCLK:
+ case SMU_FCLK:
+ case SMU_VCLK:
+ case SMU_VCLK1:
+ case SMU_DCLK:
+ case SMU_DCLK1:
+ ret = smu_v13_0_0_get_current_clk_freq_by_table(smu, clk_type, &curr_freq);
+ if (ret) {
+ dev_err(smu->adev->dev, "Failed to get current clock freq!");
+ return ret;
+ }
+
+ if (single_dpm_table->is_fine_grained) {
+ /*
+ * For fine grained dpms, there are only two dpm levels:
+ * - level 0 -> min clock freq
+ * - level 1 -> max clock freq
+ * And the current clock frequency can be any value between them.
+ * So, if the current clock frequency is not at level 0 or level 1,
+ * we will fake it as three dpm levels:
+ * - level 0 -> min clock freq
+ * - level 1 -> current actual clock freq
+ * - level 2 -> max clock freq
+ */
+ if ((single_dpm_table->dpm_levels[0].value != curr_freq) &&
+ (single_dpm_table->dpm_levels[1].value != curr_freq)) {
+ size += sysfs_emit_at(buf, size, "0: %uMhz\n",
+ single_dpm_table->dpm_levels[0].value);
+ size += sysfs_emit_at(buf, size, "1: %uMhz *\n",
+ curr_freq);
+ size += sysfs_emit_at(buf, size, "2: %uMhz\n",
+ single_dpm_table->dpm_levels[1].value);
+ } else {
+ size += sysfs_emit_at(buf, size, "0: %uMhz %s\n",
+ single_dpm_table->dpm_levels[0].value,
+ single_dpm_table->dpm_levels[0].value == curr_freq ? "*" : "");
+ size += sysfs_emit_at(buf, size, "1: %uMhz %s\n",
+ single_dpm_table->dpm_levels[1].value,
+ single_dpm_table->dpm_levels[1].value == curr_freq ? "*" : "");
+ }
+ } else {
+ for (i = 0; i < single_dpm_table->count; i++)
+ size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n",
+ i, single_dpm_table->dpm_levels[i].value,
+ single_dpm_table->dpm_levels[i].value == curr_freq ? "*" : "");
+ }
+ break;
+ case SMU_PCIE:
+ ret = smu_v13_0_0_get_smu_metrics_data(smu,
+ METRICS_PCIE_RATE,
+ &gen_speed);
+ if (ret)
+ return ret;
+
+ ret = smu_v13_0_0_get_smu_metrics_data(smu,
+ METRICS_PCIE_WIDTH,
+ &lane_width);
+ if (ret)
+ return ret;
+
+ pcie_table = &(dpm_context->dpm_tables.pcie_table);
+ for (i = 0; i < pcie_table->num_of_link_levels; i++)
+ size += sysfs_emit_at(buf, size, "%d: %s %s %dMhz %s\n", i,
+ (pcie_table->pcie_gen[i] == 0) ? "2.5GT/s," :
+ (pcie_table->pcie_gen[i] == 1) ? "5.0GT/s," :
+ (pcie_table->pcie_gen[i] == 2) ? "8.0GT/s," :
+ (pcie_table->pcie_gen[i] == 3) ? "16.0GT/s," : "",
+ (pcie_table->pcie_lane[i] == 1) ? "x1" :
+ (pcie_table->pcie_lane[i] == 2) ? "x2" :
+ (pcie_table->pcie_lane[i] == 3) ? "x4" :
+ (pcie_table->pcie_lane[i] == 4) ? "x8" :
+ (pcie_table->pcie_lane[i] == 5) ? "x12" :
+ (pcie_table->pcie_lane[i] == 6) ? "x16" : "",
+ pcie_table->clk_freq[i],
+ ((gen_speed - 1) == pcie_table->pcie_gen[i]) &&
+ (lane_width == link_width[pcie_table->pcie_lane[i]]) ?
+ "*" : "");
+ break;
+
+ default:
+ break;
+ }
+
+ return size;
+}
+
+static int smu_v13_0_0_force_clk_levels(struct smu_context *smu,
+ enum smu_clk_type clk_type,
+ uint32_t mask)
+{
+ struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
+ struct smu_13_0_dpm_context *dpm_context = smu_dpm->dpm_context;
+ struct smu_13_0_dpm_table *single_dpm_table;
+ uint32_t soft_min_level, soft_max_level;
+ uint32_t min_freq, max_freq;
+ int ret = 0;
+
+ soft_min_level = mask ? (ffs(mask) - 1) : 0;
+ soft_max_level = mask ? (fls(mask) - 1) : 0;
+
+ switch (clk_type) {
+ case SMU_GFXCLK:
+ case SMU_SCLK:
+ single_dpm_table = &(dpm_context->dpm_tables.gfx_table);
+ break;
+ case SMU_MCLK:
+ case SMU_UCLK:
+ single_dpm_table = &(dpm_context->dpm_tables.uclk_table);
+ break;
+ case SMU_SOCCLK:
+ single_dpm_table = &(dpm_context->dpm_tables.soc_table);
+ break;
+ case SMU_FCLK:
+ single_dpm_table = &(dpm_context->dpm_tables.fclk_table);
+ break;
+ case SMU_VCLK:
+ case SMU_VCLK1:
+ single_dpm_table = &(dpm_context->dpm_tables.vclk_table);
+ break;
+ case SMU_DCLK:
+ case SMU_DCLK1:
+ single_dpm_table = &(dpm_context->dpm_tables.dclk_table);
+ break;
+ default:
+ break;
+ }
+
+ switch (clk_type) {
+ case SMU_GFXCLK:
+ case SMU_SCLK:
+ case SMU_MCLK:
+ case SMU_UCLK:
+ case SMU_SOCCLK:
+ case SMU_FCLK:
+ case SMU_VCLK:
+ case SMU_VCLK1:
+ case SMU_DCLK:
+ case SMU_DCLK1:
+ if (single_dpm_table->is_fine_grained) {
+ /* There is only 2 levels for fine grained DPM */
+ soft_max_level = (soft_max_level >= 1 ? 1 : 0);
+ soft_min_level = (soft_min_level >= 1 ? 1 : 0);
+ } else {
+ if ((soft_max_level >= single_dpm_table->count) ||
+ (soft_min_level >= single_dpm_table->count))
+ return -EINVAL;
+ }
+
+ min_freq = single_dpm_table->dpm_levels[soft_min_level].value;
+ max_freq = single_dpm_table->dpm_levels[soft_max_level].value;
+
+ ret = smu_v13_0_set_soft_freq_limited_range(smu,
+ clk_type,
+ min_freq,
+ max_freq);
+ break;
+ case SMU_DCEFCLK:
+ case SMU_PCIE:
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+static int smu_v13_0_0_update_pcie_parameters(struct smu_context *smu,
+ uint32_t pcie_gen_cap,
+ uint32_t pcie_width_cap)
+{
+ struct smu_13_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context;
+ struct smu_13_0_pcie_table *pcie_table =
+ &dpm_context->dpm_tables.pcie_table;
+ uint32_t smu_pcie_arg;
+ int ret, i;
+
+ for (i = 0; i < pcie_table->num_of_link_levels; i++) {
+ if (pcie_table->pcie_gen[i] > pcie_gen_cap)
+ pcie_table->pcie_gen[i] = pcie_gen_cap;
+ if (pcie_table->pcie_lane[i] > pcie_width_cap)
+ pcie_table->pcie_lane[i] = pcie_width_cap;
+
+ smu_pcie_arg = i << 16;
+ smu_pcie_arg |= pcie_table->pcie_gen[i] << 8;
+ smu_pcie_arg |= pcie_table->pcie_lane[i];
+
+ ret = smu_cmn_send_smc_msg_with_param(smu,
+ SMU_MSG_OverridePcieParameters,
+ smu_pcie_arg,
+ NULL);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct smu_temperature_range smu13_thermal_policy[] = {
+ {-273150, 99000, 99000, -273150, 99000, 99000, -273150, 99000, 99000},
+ { 120000, 120000, 120000, 120000, 120000, 120000, 120000, 120000, 120000},
+};
+
+static int smu_v13_0_0_get_thermal_temperature_range(struct smu_context *smu,
+ struct smu_temperature_range *range)
+{
+ struct smu_table_context *table_context = &smu->smu_table;
+ struct smu_13_0_0_powerplay_table *powerplay_table =
+ table_context->power_play_table;
+ PPTable_t *pptable = smu->smu_table.driver_pptable;
+
+ if (!range)
+ return -EINVAL;
+
+ memcpy(range, &smu13_thermal_policy[0], sizeof(struct smu_temperature_range));
+
+ range->max = pptable->SkuTable.TemperatureLimit[TEMP_EDGE] *
+ SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ range->edge_emergency_max = (pptable->SkuTable.TemperatureLimit[TEMP_EDGE] + CTF_OFFSET_EDGE) *
+ SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ range->hotspot_crit_max = pptable->SkuTable.TemperatureLimit[TEMP_HOTSPOT] *
+ SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ range->hotspot_emergency_max = (pptable->SkuTable.TemperatureLimit[TEMP_HOTSPOT] + CTF_OFFSET_HOTSPOT) *
+ SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ range->mem_crit_max = pptable->SkuTable.TemperatureLimit[TEMP_MEM] *
+ SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ range->mem_emergency_max = (pptable->SkuTable.TemperatureLimit[TEMP_MEM] + CTF_OFFSET_MEM)*
+ SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ range->software_shutdown_temp = powerplay_table->software_shutdown_temp;
+
+ return 0;
+}
+
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+static ssize_t smu_v13_0_0_get_gpu_metrics(struct smu_context *smu,
+ void **table)
+{
+ struct smu_table_context *smu_table = &smu->smu_table;
+ struct gpu_metrics_v1_3 *gpu_metrics =
+ (struct gpu_metrics_v1_3 *)smu_table->gpu_metrics_table;
+ SmuMetricsExternal_t metrics_ext;
+ SmuMetrics_t *metrics = &metrics_ext.SmuMetrics;
+ int ret = 0;
+
+ ret = smu_cmn_get_metrics_table(smu,
+ &metrics_ext,
+ true);
+ if (ret)
+ return ret;
+
+ smu_cmn_init_soft_gpu_metrics(gpu_metrics, 1, 3);
+
+ gpu_metrics->temperature_edge = metrics->AvgTemperature[TEMP_EDGE];
+ gpu_metrics->temperature_hotspot = metrics->AvgTemperature[TEMP_HOTSPOT];
+ gpu_metrics->temperature_mem = metrics->AvgTemperature[TEMP_MEM];
+ gpu_metrics->temperature_vrgfx = metrics->AvgTemperature[TEMP_VR_GFX];
+ gpu_metrics->temperature_vrsoc = metrics->AvgTemperature[TEMP_VR_SOC];
+ gpu_metrics->temperature_vrmem = MAX(metrics->AvgTemperature[TEMP_VR_MEM0],
+ metrics->AvgTemperature[TEMP_VR_MEM1]);
+
+ gpu_metrics->average_gfx_activity = metrics->AverageGfxActivity;
+ gpu_metrics->average_umc_activity = metrics->AverageUclkActivity;
+ gpu_metrics->average_mm_activity = MAX(metrics->Vcn0ActivityPercentage,
+ metrics->Vcn1ActivityPercentage);
+
+ gpu_metrics->average_socket_power = metrics->AverageSocketPower;
+ gpu_metrics->energy_accumulator = metrics->EnergyAccumulator;
+
+ if (metrics->AverageGfxActivity <= SMU_13_0_0_BUSY_THRESHOLD)
+ gpu_metrics->average_gfxclk_frequency = metrics->AverageGfxclkFrequencyPostDs;
+ else
+ gpu_metrics->average_gfxclk_frequency = metrics->AverageGfxclkFrequencyPreDs;
+
+ if (metrics->AverageUclkActivity <= SMU_13_0_0_BUSY_THRESHOLD)
+ gpu_metrics->average_uclk_frequency = metrics->AverageMemclkFrequencyPostDs;
+ else
+ gpu_metrics->average_uclk_frequency = metrics->AverageMemclkFrequencyPreDs;
+
+ gpu_metrics->average_vclk0_frequency = metrics->AverageVclk0Frequency;
+ gpu_metrics->average_dclk0_frequency = metrics->AverageDclk0Frequency;
+ gpu_metrics->average_vclk1_frequency = metrics->AverageVclk1Frequency;
+ gpu_metrics->average_dclk1_frequency = metrics->AverageDclk1Frequency;
+
+ gpu_metrics->current_gfxclk = metrics->CurrClock[PPCLK_GFXCLK];
+ gpu_metrics->current_socclk = metrics->CurrClock[PPCLK_SOCCLK];
+ gpu_metrics->current_uclk = metrics->CurrClock[PPCLK_UCLK];
+ gpu_metrics->current_vclk0 = metrics->CurrClock[PPCLK_VCLK_0];
+ gpu_metrics->current_dclk0 = metrics->CurrClock[PPCLK_DCLK_0];
+ gpu_metrics->current_vclk1 = metrics->CurrClock[PPCLK_VCLK_1];
+ gpu_metrics->current_dclk1 = metrics->CurrClock[PPCLK_DCLK_1];
+
+ gpu_metrics->throttle_status =
+ smu_v13_0_get_throttler_status(metrics);
+ gpu_metrics->indep_throttle_status =
+ smu_cmn_get_indep_throttler_status(gpu_metrics->throttle_status,
+ smu_v13_0_0_throttler_map);
+
+ gpu_metrics->current_fan_speed = metrics->AvgFanRpm;
+
+ gpu_metrics->pcie_link_width = metrics->PcieWidth;
+ gpu_metrics->pcie_link_speed = metrics->PcieRate;
+
+ gpu_metrics->system_clock_counter = ktime_get_boottime_ns();
+
+ gpu_metrics->voltage_gfx = metrics->AvgVoltage[SVI_PLANE_GFX];
+ gpu_metrics->voltage_soc = metrics->AvgVoltage[SVI_PLANE_SOC];
+ gpu_metrics->voltage_mem = metrics->AvgVoltage[SVI_PLANE_VMEMP];
+
+ *table = (void *)gpu_metrics;
+
+ return sizeof(struct gpu_metrics_v1_3);
+}
+
+static int smu_v13_0_0_populate_umd_state_clk(struct smu_context *smu)
+{
+ struct smu_13_0_dpm_context *dpm_context =
+ smu->smu_dpm.dpm_context;
+ struct smu_13_0_dpm_table *gfx_table =
+ &dpm_context->dpm_tables.gfx_table;
+ struct smu_13_0_dpm_table *mem_table =
+ &dpm_context->dpm_tables.uclk_table;
+ struct smu_13_0_dpm_table *soc_table =
+ &dpm_context->dpm_tables.soc_table;
+ struct smu_13_0_dpm_table *vclk_table =
+ &dpm_context->dpm_tables.vclk_table;
+ struct smu_13_0_dpm_table *dclk_table =
+ &dpm_context->dpm_tables.dclk_table;
+ struct smu_13_0_dpm_table *fclk_table =
+ &dpm_context->dpm_tables.fclk_table;
+ struct smu_umd_pstate_table *pstate_table =
+ &smu->pstate_table;
+
+ pstate_table->gfxclk_pstate.min = gfx_table->min;
+ pstate_table->gfxclk_pstate.peak = gfx_table->max;
+
+ pstate_table->uclk_pstate.min = mem_table->min;
+ pstate_table->uclk_pstate.peak = mem_table->max;
+
+ pstate_table->socclk_pstate.min = soc_table->min;
+ pstate_table->socclk_pstate.peak = soc_table->max;
+
+ pstate_table->vclk_pstate.min = vclk_table->min;
+ pstate_table->vclk_pstate.peak = vclk_table->max;
+
+ pstate_table->dclk_pstate.min = dclk_table->min;
+ pstate_table->dclk_pstate.peak = dclk_table->max;
+
+ pstate_table->fclk_pstate.min = fclk_table->min;
+ pstate_table->fclk_pstate.peak = fclk_table->max;
+
+ /*
+ * For now, just use the mininum clock frequency.
+ * TODO: update them when the real pstate settings available
+ */
+ pstate_table->gfxclk_pstate.standard = gfx_table->min;
+ pstate_table->uclk_pstate.standard = mem_table->min;
+ pstate_table->socclk_pstate.standard = soc_table->min;
+ pstate_table->vclk_pstate.standard = vclk_table->min;
+ pstate_table->dclk_pstate.standard = dclk_table->min;
+ pstate_table->fclk_pstate.standard = fclk_table->min;
+
+ return 0;
+}
+
+static void smu_v13_0_0_get_unique_id(struct smu_context *smu)
+{
+ struct smu_table_context *smu_table = &smu->smu_table;
+ SmuMetrics_t *metrics =
+ &(((SmuMetricsExternal_t *)(smu_table->metrics_table))->SmuMetrics);
+ struct amdgpu_device *adev = smu->adev;
+ uint32_t upper32 = 0, lower32 = 0;
+ int ret;
+
+ ret = smu_cmn_get_metrics_table(smu, NULL, false);
+ if (ret)
+ goto out;
+
+ upper32 = metrics->PublicSerialNumberUpper;
+ lower32 = metrics->PublicSerialNumberLower;
+
+out:
+ adev->unique_id = ((uint64_t)upper32 << 32) | lower32;
+ if (adev->serial[0] == '\0')
+ sprintf(adev->serial, "%016llx", adev->unique_id);
+}
+
+static int smu_v13_0_0_get_fan_speed_pwm(struct smu_context *smu,
+ uint32_t *speed)
+{
+ if (!speed)
+ return -EINVAL;
+
+ return smu_v13_0_0_get_smu_metrics_data(smu,
+ METRICS_CURR_FANPWM,
+ speed);
+}
+
+static int smu_v13_0_0_get_fan_speed_rpm(struct smu_context *smu,
+ uint32_t *speed)
+{
+ if (!speed)
+ return -EINVAL;
+
+ return smu_v13_0_0_get_smu_metrics_data(smu,
+ METRICS_CURR_FANSPEED,
+ speed);
+}
+
+static int smu_v13_0_0_enable_mgpu_fan_boost(struct smu_context *smu)
+{
+ struct smu_table_context *table_context = &smu->smu_table;
+ PPTable_t *pptable = table_context->driver_pptable;
+ SkuTable_t *skutable = &pptable->SkuTable;
+
+ /*
+ * Skip the MGpuFanBoost setting for those ASICs
+ * which do not support it
+ */
+ if (skutable->MGpuAcousticLimitRpmThreshold == 0)
+ return 0;
+
+ return smu_cmn_send_smc_msg_with_param(smu,
+ SMU_MSG_SetMGpuFanBoostLimitRpm,
+ 0,
+ NULL);
+}
+
+static int smu_v13_0_0_get_power_limit(struct smu_context *smu,
+ uint32_t *current_power_limit,
+ uint32_t *default_power_limit,
+ uint32_t *max_power_limit)
+{
+ struct smu_table_context *table_context = &smu->smu_table;
+ struct smu_13_0_0_powerplay_table *powerplay_table =
+ (struct smu_13_0_0_powerplay_table *)table_context->power_play_table;
+ PPTable_t *pptable = table_context->driver_pptable;
+ SkuTable_t *skutable = &pptable->SkuTable;
+ uint32_t power_limit, od_percent;
+
+ if (smu_v13_0_get_current_power_limit(smu, &power_limit))
+ power_limit = smu->adev->pm.ac_power ?
+ skutable->SocketPowerLimitAc[PPT_THROTTLER_PPT0] :
+ skutable->SocketPowerLimitDc[PPT_THROTTLER_PPT0];
+
+ if (current_power_limit)
+ *current_power_limit = power_limit;
+ if (default_power_limit)
+ *default_power_limit = power_limit;
+
+ if (max_power_limit) {
+ if (smu->od_enabled) {
+ od_percent = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_13_0_0_ODSETTING_POWERPERCENTAGE]);
+
+ dev_dbg(smu->adev->dev, "ODSETTING_POWERPERCENTAGE: %d (default: %d)\n", od_percent, power_limit);
+
+ power_limit *= (100 + od_percent);
+ power_limit /= 100;
+ }
+ *max_power_limit = power_limit;
+ }
+
+ return 0;
+}
+
+static int smu_v13_0_0_get_power_profile_mode(struct smu_context *smu,
+ char *buf)
+{
+ DpmActivityMonitorCoeffIntExternal_t activity_monitor_external;
+ DpmActivityMonitorCoeffInt_t *activity_monitor =
+ &(activity_monitor_external.DpmActivityMonitorCoeffInt);
+ static const char *title[] = {
+ "PROFILE_INDEX(NAME)",
+ "CLOCK_TYPE(NAME)",
+ "FPS",
+ "MinActiveFreqType",
+ "MinActiveFreq",
+ "BoosterFreqType",
+ "BoosterFreq",
+ "PD_Data_limit_c",
+ "PD_Data_error_coeff",
+ "PD_Data_error_rate_coeff"};
+ int16_t workload_type = 0;
+ uint32_t i, size = 0;
+ int result = 0;
+
+ if (!buf)
+ return -EINVAL;
+
+ size += sysfs_emit_at(buf, size, "%16s %s %s %s %s %s %s %s %s %s\n",
+ title[0], title[1], title[2], title[3], title[4], title[5],
+ title[6], title[7], title[8], title[9]);
+
+ for (i = 0; i <= PP_SMC_POWER_PROFILE_CUSTOM; i++) {
+ /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
+ workload_type = smu_cmn_to_asic_specific_index(smu,
+ CMN2ASIC_MAPPING_WORKLOAD,
+ i);
+ if (workload_type < 0)
+ return -EINVAL;
+
+ result = smu_cmn_update_table(smu,
+ SMU_TABLE_ACTIVITY_MONITOR_COEFF,
+ workload_type,
+ (void *)(&activity_monitor_external),
+ false);
+ if (result) {
+ dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
+ return result;
+ }
+
+ size += sysfs_emit_at(buf, size, "%2d %14s%s:\n",
+ i, amdgpu_pp_profile_name[i], (i == smu->power_profile_mode) ? "*" : " ");
+
+ size += sysfs_emit_at(buf, size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d\n",
+ " ",
+ 0,
+ "GFXCLK",
+ activity_monitor->Gfx_FPS,
+ activity_monitor->Gfx_MinActiveFreqType,
+ activity_monitor->Gfx_MinActiveFreq,
+ activity_monitor->Gfx_BoosterFreqType,
+ activity_monitor->Gfx_BoosterFreq,
+ activity_monitor->Gfx_PD_Data_limit_c,
+ activity_monitor->Gfx_PD_Data_error_coeff,
+ activity_monitor->Gfx_PD_Data_error_rate_coeff);
+
+ size += sysfs_emit_at(buf, size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d\n",
+ " ",
+ 1,
+ "FCLK",
+ activity_monitor->Fclk_FPS,
+ activity_monitor->Fclk_MinActiveFreqType,
+ activity_monitor->Fclk_MinActiveFreq,
+ activity_monitor->Fclk_BoosterFreqType,
+ activity_monitor->Fclk_BoosterFreq,
+ activity_monitor->Fclk_PD_Data_limit_c,
+ activity_monitor->Fclk_PD_Data_error_coeff,
+ activity_monitor->Fclk_PD_Data_error_rate_coeff);
+ }
+
+ return size;
+}
+
+static int smu_v13_0_0_set_power_profile_mode(struct smu_context *smu,
+ long *input,
+ uint32_t size)
+{
+ DpmActivityMonitorCoeffIntExternal_t activity_monitor_external;
+ DpmActivityMonitorCoeffInt_t *activity_monitor =
+ &(activity_monitor_external.DpmActivityMonitorCoeffInt);
+ int workload_type, ret = 0;
+
+ smu->power_profile_mode = input[size];
+
+ if (smu->power_profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) {
+ dev_err(smu->adev->dev, "Invalid power profile mode %d\n", smu->power_profile_mode);
+ return -EINVAL;
+ }
+
+ if (smu->power_profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) {
+ ret = smu_cmn_update_table(smu,
+ SMU_TABLE_ACTIVITY_MONITOR_COEFF,
+ WORKLOAD_PPLIB_CUSTOM_BIT,
+ (void *)(&activity_monitor_external),
+ false);
+ if (ret) {
+ dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
+ return ret;
+ }
+
+ switch (input[0]) {
+ case 0: /* Gfxclk */
+ activity_monitor->Gfx_FPS = input[1];
+ activity_monitor->Gfx_MinActiveFreqType = input[2];
+ activity_monitor->Gfx_MinActiveFreq = input[3];
+ activity_monitor->Gfx_BoosterFreqType = input[4];
+ activity_monitor->Gfx_BoosterFreq = input[5];
+ activity_monitor->Gfx_PD_Data_limit_c = input[6];
+ activity_monitor->Gfx_PD_Data_error_coeff = input[7];
+ activity_monitor->Gfx_PD_Data_error_rate_coeff = input[8];
+ break;
+ case 1: /* Fclk */
+ activity_monitor->Fclk_FPS = input[1];
+ activity_monitor->Fclk_MinActiveFreqType = input[2];
+ activity_monitor->Fclk_MinActiveFreq = input[3];
+ activity_monitor->Fclk_BoosterFreqType = input[4];
+ activity_monitor->Fclk_BoosterFreq = input[5];
+ activity_monitor->Fclk_PD_Data_limit_c = input[6];
+ activity_monitor->Fclk_PD_Data_error_coeff = input[7];
+ activity_monitor->Fclk_PD_Data_error_rate_coeff = input[8];
+ break;
+ }
+
+ ret = smu_cmn_update_table(smu,
+ SMU_TABLE_ACTIVITY_MONITOR_COEFF,
+ WORKLOAD_PPLIB_CUSTOM_BIT,
+ (void *)(&activity_monitor_external),
+ true);
+ if (ret) {
+ dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__);
+ return ret;
+ }
+ }
+
+ /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
+ workload_type = smu_cmn_to_asic_specific_index(smu,
+ CMN2ASIC_MAPPING_WORKLOAD,
+ smu->power_profile_mode);
+ if (workload_type < 0)
+ return -EINVAL;
+
+ return smu_cmn_send_smc_msg_with_param(smu,
+ SMU_MSG_SetWorkloadMask,
+ 1 << workload_type,
+ NULL);
+}
+
+static const struct pptable_funcs smu_v13_0_0_ppt_funcs = {
+ .get_allowed_feature_mask = smu_v13_0_0_get_allowed_feature_mask,
+ .set_default_dpm_table = smu_v13_0_0_set_default_dpm_table,
+ .is_dpm_running = smu_v13_0_0_is_dpm_running,
+ .dump_pptable = smu_v13_0_0_dump_pptable,
+ .init_microcode = smu_v13_0_init_microcode,
+ .load_microcode = smu_v13_0_load_microcode,
+ .init_smc_tables = smu_v13_0_0_init_smc_tables,
+ .init_power = smu_v13_0_init_power,
+ .fini_power = smu_v13_0_fini_power,
+ .check_fw_status = smu_v13_0_check_fw_status,
+ .setup_pptable = smu_v13_0_0_setup_pptable,
+ .check_fw_version = smu_v13_0_check_fw_version,
+ .write_pptable = smu_cmn_write_pptable,
+ .set_driver_table_location = smu_v13_0_set_driver_table_location,
+ .system_features_control = smu_v13_0_0_system_features_control,
+ .set_allowed_mask = smu_v13_0_set_allowed_mask,
+ .get_enabled_mask = smu_cmn_get_enabled_mask,
+ .dpm_set_vcn_enable = smu_v13_0_set_vcn_enable,
+ .dpm_set_jpeg_enable = smu_v13_0_set_jpeg_enable,
+ .get_dpm_ultimate_freq = smu_v13_0_get_dpm_ultimate_freq,
+ .get_vbios_bootup_values = smu_v13_0_get_vbios_bootup_values,
+ .read_sensor = smu_v13_0_0_read_sensor,
+ .feature_is_enabled = smu_cmn_feature_is_enabled,
+ .print_clk_levels = smu_v13_0_0_print_clk_levels,
+ .force_clk_levels = smu_v13_0_0_force_clk_levels,
+ .update_pcie_parameters = smu_v13_0_0_update_pcie_parameters,
+ .get_thermal_temperature_range = smu_v13_0_0_get_thermal_temperature_range,
+ .register_irq_handler = smu_v13_0_register_irq_handler,
+ .enable_thermal_alert = smu_v13_0_enable_thermal_alert,
+ .disable_thermal_alert = smu_v13_0_disable_thermal_alert,
+ .notify_memory_pool_location = smu_v13_0_notify_memory_pool_location,
+ .get_gpu_metrics = smu_v13_0_0_get_gpu_metrics,
+ .set_soft_freq_limited_range = smu_v13_0_set_soft_freq_limited_range,
+ .init_pptable_microcode = smu_v13_0_init_pptable_microcode,
+ .populate_umd_state_clk = smu_v13_0_0_populate_umd_state_clk,
+ .set_performance_level = smu_v13_0_set_performance_level,
+ .gfx_off_control = smu_v13_0_gfx_off_control,
+ .get_unique_id = smu_v13_0_0_get_unique_id,
+ .get_fan_speed_pwm = smu_v13_0_0_get_fan_speed_pwm,
+ .get_fan_speed_rpm = smu_v13_0_0_get_fan_speed_rpm,
+ .set_fan_speed_pwm = smu_v13_0_set_fan_speed_pwm,
+ .set_fan_speed_rpm = smu_v13_0_set_fan_speed_rpm,
+ .get_fan_control_mode = smu_v13_0_get_fan_control_mode,
+ .set_fan_control_mode = smu_v13_0_set_fan_control_mode,
+ .enable_mgpu_fan_boost = smu_v13_0_0_enable_mgpu_fan_boost,
+ .get_power_limit = smu_v13_0_0_get_power_limit,
+ .set_power_limit = smu_v13_0_set_power_limit,
+ .set_power_source = smu_v13_0_set_power_source,
+ .get_power_profile_mode = smu_v13_0_0_get_power_profile_mode,
+ .set_power_profile_mode = smu_v13_0_0_set_power_profile_mode,
+ .run_btc = smu_v13_0_run_btc,
+ .get_pp_feature_mask = smu_cmn_get_pp_feature_mask,
+ .set_pp_feature_mask = smu_cmn_set_pp_feature_mask,
+ .set_tool_table_location = smu_v13_0_set_tool_table_location,
+ .deep_sleep_control = smu_v13_0_deep_sleep_control,
+ .gfx_ulv_control = smu_v13_0_gfx_ulv_control,
+ .baco_is_support = smu_v13_0_baco_is_support,
+ .baco_get_state = smu_v13_0_baco_get_state,
+ .baco_set_state = smu_v13_0_baco_set_state,
+ .baco_enter = smu_v13_0_baco_enter,
+ .baco_exit = smu_v13_0_baco_exit,
+};
+
+void smu_v13_0_0_set_ppt_funcs(struct smu_context *smu)
+{
+ smu->ppt_funcs = &smu_v13_0_0_ppt_funcs;
+ smu->message_map = smu_v13_0_0_message_map;
+ smu->clock_map = smu_v13_0_0_clk_map;
+ smu->feature_map = smu_v13_0_0_feature_mask_map;
+ smu->table_map = smu_v13_0_0_table_map;
+ smu->pwr_src_map = smu_v13_0_0_pwr_src_map;
+ smu->workload_map = smu_v13_0_0_workload_map;
+}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.h b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.h
new file mode 100644
index 000000000000..ede494856dbd
--- /dev/null
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2021 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+#ifndef __SMU_V13_0_0_PPT_H__
+#define __SMU_V13_0_0_PPT_H__
+
+extern void smu_v13_0_0_set_ppt_funcs(struct smu_context *smu);
+
+#endif
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.c
new file mode 100644
index 000000000000..7d6ff141b43f
--- /dev/null
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.c
@@ -0,0 +1,1044 @@
+/*
+ * Copyright 2022 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "smu_types.h"
+#define SWSMU_CODE_LAYER_L2
+
+#include "amdgpu.h"
+#include "amdgpu_smu.h"
+#include "smu_v13_0.h"
+#include "smu13_driver_if_v13_0_4.h"
+#include "smu_v13_0_4_ppt.h"
+#include "smu_v13_0_4_ppsmc.h"
+#include "smu_v13_0_4_pmfw.h"
+#include "smu_cmn.h"
+
+/*
+ * DO NOT use these for err/warn/info/debug messages.
+ * Use dev_err, dev_warn, dev_info and dev_dbg instead.
+ * They are more MGPU friendly.
+ */
+#undef pr_err
+#undef pr_warn
+#undef pr_info
+#undef pr_debug
+
+#define FEATURE_MASK(feature) (1ULL << feature)
+
+#define SMC_DPM_FEATURE ( \
+ FEATURE_MASK(FEATURE_CCLK_DPM_BIT) | \
+ FEATURE_MASK(FEATURE_VCN_DPM_BIT) | \
+ FEATURE_MASK(FEATURE_FCLK_DPM_BIT) | \
+ FEATURE_MASK(FEATURE_SOCCLK_DPM_BIT) | \
+ FEATURE_MASK(FEATURE_MP0CLK_DPM_BIT) | \
+ FEATURE_MASK(FEATURE_LCLK_DPM_BIT) | \
+ FEATURE_MASK(FEATURE_SHUBCLK_DPM_BIT) | \
+ FEATURE_MASK(FEATURE_DCFCLK_DPM_BIT) | \
+ FEATURE_MASK(FEATURE_ISP_DPM_BIT) | \
+ FEATURE_MASK(FEATURE_IPU_DPM_BIT) | \
+ FEATURE_MASK(FEATURE_GFX_DPM_BIT))
+
+static struct cmn2asic_msg_mapping smu_v13_0_4_message_map[SMU_MSG_MAX_COUNT] = {
+ MSG_MAP(TestMessage, PPSMC_MSG_TestMessage, 1),
+ MSG_MAP(GetSmuVersion, PPSMC_MSG_GetPmfwVersion, 1),
+ MSG_MAP(GetDriverIfVersion, PPSMC_MSG_GetDriverIfVersion, 1),
+ MSG_MAP(EnableGfxOff, PPSMC_MSG_EnableGfxOff, 1),
+ MSG_MAP(AllowGfxOff, PPSMC_MSG_AllowGfxOff, 1),
+ MSG_MAP(DisallowGfxOff, PPSMC_MSG_DisallowGfxOff, 1),
+ MSG_MAP(PowerDownVcn, PPSMC_MSG_PowerDownVcn, 1),
+ MSG_MAP(PowerUpVcn, PPSMC_MSG_PowerUpVcn, 1),
+ MSG_MAP(SetHardMinVcn, PPSMC_MSG_SetHardMinVcn, 1),
+ MSG_MAP(PrepareMp1ForUnload, PPSMC_MSG_PrepareMp1ForUnload, 1),
+ MSG_MAP(SetDriverDramAddrHigh, PPSMC_MSG_SetDriverDramAddrHigh, 1),
+ MSG_MAP(SetDriverDramAddrLow, PPSMC_MSG_SetDriverDramAddrLow, 1),
+ MSG_MAP(TransferTableSmu2Dram, PPSMC_MSG_TransferTableSmu2Dram, 1),
+ MSG_MAP(TransferTableDram2Smu, PPSMC_MSG_TransferTableDram2Smu, 1),
+ MSG_MAP(GfxDeviceDriverReset, PPSMC_MSG_GfxDeviceDriverReset, 1),
+ MSG_MAP(GetEnabledSmuFeatures, PPSMC_MSG_GetEnabledSmuFeatures, 1),
+ MSG_MAP(SetHardMinSocclkByFreq, PPSMC_MSG_SetHardMinSocclkByFreq, 1),
+ MSG_MAP(SetSoftMinVcn, PPSMC_MSG_SetSoftMinVcn, 1),
+ MSG_MAP(GetGfxclkFrequency, PPSMC_MSG_GetGfxclkFrequency, 1),
+ MSG_MAP(GetFclkFrequency, PPSMC_MSG_GetFclkFrequency, 1),
+ MSG_MAP(SetSoftMaxGfxClk, PPSMC_MSG_SetSoftMaxGfxClk, 1),
+ MSG_MAP(SetHardMinGfxClk, PPSMC_MSG_SetHardMinGfxClk, 1),
+ MSG_MAP(SetSoftMaxSocclkByFreq, PPSMC_MSG_SetSoftMaxSocclkByFreq, 1),
+ MSG_MAP(SetSoftMaxFclkByFreq, PPSMC_MSG_SetSoftMaxFclkByFreq, 1),
+ MSG_MAP(SetSoftMaxVcn, PPSMC_MSG_SetSoftMaxVcn, 1),
+ MSG_MAP(SetPowerLimitPercentage, PPSMC_MSG_SetPowerLimitPercentage, 1),
+ MSG_MAP(PowerDownJpeg, PPSMC_MSG_PowerDownJpeg, 1),
+ MSG_MAP(PowerUpJpeg, PPSMC_MSG_PowerUpJpeg, 1),
+ MSG_MAP(SetHardMinFclkByFreq, PPSMC_MSG_SetHardMinFclkByFreq, 1),
+ MSG_MAP(SetSoftMinSocclkByFreq, PPSMC_MSG_SetSoftMinSocclkByFreq, 1),
+ MSG_MAP(EnableGfxImu, PPSMC_MSG_EnableGfxImu, 1),
+ MSG_MAP(PowerUpIspByTile, PPSMC_MSG_PowerUpIspByTile, 1),
+ MSG_MAP(PowerDownIspByTile, PPSMC_MSG_PowerDownIspByTile, 1),
+};
+
+static struct cmn2asic_mapping smu_v13_0_4_feature_mask_map[SMU_FEATURE_COUNT] = {
+ FEA_MAP(CCLK_DPM),
+ FEA_MAP(FAN_CONTROLLER),
+ FEA_MAP(PPT),
+ FEA_MAP(TDC),
+ FEA_MAP(THERMAL),
+ FEA_MAP(VCN_DPM),
+ FEA_MAP_REVERSE(FCLK),
+ FEA_MAP_REVERSE(SOCCLK),
+ FEA_MAP(LCLK_DPM),
+ FEA_MAP(SHUBCLK_DPM),
+ FEA_MAP(DCFCLK_DPM),
+ FEA_MAP_HALF_REVERSE(GFX),
+ FEA_MAP(DS_GFXCLK),
+ FEA_MAP(DS_SOCCLK),
+ FEA_MAP(DS_LCLK),
+ FEA_MAP(DS_DCFCLK),
+ FEA_MAP(DS_FCLK),
+ FEA_MAP(DS_MP1CLK),
+ FEA_MAP(DS_MP0CLK),
+ FEA_MAP(GFX_DEM),
+ FEA_MAP(PSI),
+ FEA_MAP(PROCHOT),
+ FEA_MAP(CPUOFF),
+ FEA_MAP(STAPM),
+ FEA_MAP(S0I3),
+ FEA_MAP(PERF_LIMIT),
+ FEA_MAP(CORE_DLDO),
+ FEA_MAP(DS_VCN),
+ FEA_MAP(CPPC),
+ FEA_MAP(DF_CSTATES),
+ FEA_MAP(ATHUB_PG),
+};
+
+static struct cmn2asic_mapping smu_v13_0_4_table_map[SMU_TABLE_COUNT] = {
+ TAB_MAP_VALID(WATERMARKS),
+ TAB_MAP_VALID(SMU_METRICS),
+ TAB_MAP_VALID(CUSTOM_DPM),
+ TAB_MAP_VALID(DPMCLOCKS),
+};
+
+static int smu_v13_0_4_init_smc_tables(struct smu_context *smu)
+{
+ struct smu_table_context *smu_table = &smu->smu_table;
+ struct smu_table *tables = smu_table->tables;
+
+ SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, sizeof(Watermarks_t),
+ PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
+ SMU_TABLE_INIT(tables, SMU_TABLE_DPMCLOCKS, sizeof(DpmClocks_t),
+ PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
+ SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_t),
+ PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
+
+ smu_table->clocks_table = kzalloc(sizeof(DpmClocks_t), GFP_KERNEL);
+ if (!smu_table->clocks_table)
+ goto err0_out;
+
+ smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL);
+ if (!smu_table->metrics_table)
+ goto err1_out;
+ smu_table->metrics_time = 0;
+
+ smu_table->watermarks_table = kzalloc(sizeof(Watermarks_t), GFP_KERNEL);
+ if (!smu_table->watermarks_table)
+ goto err2_out;
+
+ smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v2_1);
+ smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL);
+ if (!smu_table->gpu_metrics_table)
+ goto err3_out;
+
+ return 0;
+
+err3_out:
+ kfree(smu_table->watermarks_table);
+err2_out:
+ kfree(smu_table->metrics_table);
+err1_out:
+ kfree(smu_table->clocks_table);
+err0_out:
+ return -ENOMEM;
+}
+
+static int smu_v13_0_4_fini_smc_tables(struct smu_context *smu)
+{
+ struct smu_table_context *smu_table = &smu->smu_table;
+
+ kfree(smu_table->clocks_table);
+ smu_table->clocks_table = NULL;
+
+ kfree(smu_table->metrics_table);
+ smu_table->metrics_table = NULL;
+
+ kfree(smu_table->watermarks_table);
+ smu_table->watermarks_table = NULL;
+
+ return 0;
+}
+
+static bool smu_v13_0_4_is_dpm_running(struct smu_context *smu)
+{
+ int ret = 0;
+ uint64_t feature_enabled;
+
+ ret = smu_cmn_get_enabled_mask(smu, &feature_enabled);
+
+ if (ret)
+ return false;
+
+ return !!(feature_enabled & SMC_DPM_FEATURE);
+}
+
+static int smu_v13_0_4_system_features_control(struct smu_context *smu, bool en)
+{
+ struct amdgpu_device *adev = smu->adev;
+ int ret = 0;
+ /* SMU fw need this message to trigger IMU to complete the initialization */
+ if (en)
+ ret = smu_cmn_send_smc_msg(smu, SMU_MSG_EnableGfxImu, NULL);
+ else {
+ if (!adev->in_s0ix)
+ ret = smu_cmn_send_smc_msg(smu,
+ SMU_MSG_PrepareMp1ForUnload,
+ NULL);
+ }
+ return ret;
+}
+
+static int smu_v13_0_4_post_smu_init(struct smu_context *smu)
+{
+ struct amdgpu_device *adev = smu->adev;
+ int ret = 0;
+
+ /* allow message will be sent after enable message */
+ ret = smu_cmn_send_smc_msg(smu, SMU_MSG_EnableGfxOff, NULL);
+ if (ret)
+ dev_err(adev->dev, "Failed to Enable GfxOff!\n");
+ return ret;
+}
+
+static ssize_t smu_v13_0_4_get_gpu_metrics(struct smu_context *smu,
+ void **table)
+{
+ struct smu_table_context *smu_table = &smu->smu_table;
+ struct gpu_metrics_v2_1 *gpu_metrics =
+ (struct gpu_metrics_v2_1 *)smu_table->gpu_metrics_table;
+ SmuMetrics_t metrics;
+ int ret = 0;
+
+ ret = smu_cmn_get_metrics_table(smu, &metrics, true);
+ if (ret)
+ return ret;
+
+ smu_cmn_init_soft_gpu_metrics(gpu_metrics, 2, 1);
+
+ gpu_metrics->temperature_gfx = metrics.GfxTemperature;
+ gpu_metrics->temperature_soc = metrics.SocTemperature;
+ memcpy(&gpu_metrics->temperature_core[0],
+ &metrics.CoreTemperature[0],
+ sizeof(uint16_t) * 8);
+ gpu_metrics->temperature_l3[0] = metrics.L3Temperature;
+
+ gpu_metrics->average_gfx_activity = metrics.GfxActivity;
+ gpu_metrics->average_mm_activity = metrics.UvdActivity;
+
+ gpu_metrics->average_socket_power = metrics.CurrentSocketPower;
+ gpu_metrics->average_gfx_power = metrics.Power[0];
+ gpu_metrics->average_soc_power = metrics.Power[1];
+ memcpy(&gpu_metrics->average_core_power[0],
+ &metrics.CorePower[0],
+ sizeof(uint16_t) * 8);
+
+ gpu_metrics->average_gfxclk_frequency = metrics.GfxclkFrequency;
+ gpu_metrics->average_socclk_frequency = metrics.SocclkFrequency;
+ gpu_metrics->average_uclk_frequency = metrics.MemclkFrequency;
+ gpu_metrics->average_fclk_frequency = metrics.MemclkFrequency;
+ gpu_metrics->average_vclk_frequency = metrics.VclkFrequency;
+ gpu_metrics->average_dclk_frequency = metrics.DclkFrequency;
+
+ memcpy(&gpu_metrics->current_coreclk[0],
+ &metrics.CoreFrequency[0],
+ sizeof(uint16_t) * 8);
+ gpu_metrics->current_l3clk[0] = metrics.L3Frequency;
+
+ gpu_metrics->throttle_status = metrics.ThrottlerStatus;
+
+ gpu_metrics->system_clock_counter = ktime_get_boottime_ns();
+
+ *table = (void *)gpu_metrics;
+
+ return sizeof(struct gpu_metrics_v2_1);
+}
+
+static int smu_v13_0_4_get_smu_metrics_data(struct smu_context *smu,
+ MetricsMember_t member,
+ uint32_t *value)
+{
+ struct smu_table_context *smu_table = &smu->smu_table;
+
+ SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table;
+ int ret = 0;
+
+ ret = smu_cmn_get_metrics_table(smu, NULL, false);
+ if (ret)
+ return ret;
+
+ switch (member) {
+ case METRICS_AVERAGE_GFXCLK:
+ *value = metrics->GfxclkFrequency;
+ break;
+ case METRICS_AVERAGE_SOCCLK:
+ *value = metrics->SocclkFrequency;
+ break;
+ case METRICS_AVERAGE_VCLK:
+ *value = metrics->VclkFrequency;
+ break;
+ case METRICS_AVERAGE_DCLK:
+ *value = metrics->DclkFrequency;
+ break;
+ case METRICS_AVERAGE_UCLK:
+ *value = metrics->MemclkFrequency;
+ break;
+ case METRICS_AVERAGE_GFXACTIVITY:
+ *value = metrics->GfxActivity / 100;
+ break;
+ case METRICS_AVERAGE_VCNACTIVITY:
+ *value = metrics->UvdActivity;
+ break;
+ case METRICS_AVERAGE_SOCKETPOWER:
+ *value = (metrics->CurrentSocketPower << 8) / 1000;
+ break;
+ case METRICS_TEMPERATURE_EDGE:
+ *value = metrics->GfxTemperature / 100 *
+ SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ break;
+ case METRICS_TEMPERATURE_HOTSPOT:
+ *value = metrics->SocTemperature / 100 *
+ SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ break;
+ case METRICS_THROTTLER_STATUS:
+ *value = metrics->ThrottlerStatus;
+ break;
+ case METRICS_VOLTAGE_VDDGFX:
+ *value = metrics->Voltage[0];
+ break;
+ case METRICS_VOLTAGE_VDDSOC:
+ *value = metrics->Voltage[1];
+ break;
+ case METRICS_SS_APU_SHARE:
+ /* return the percentage of APU power with respect to APU's power limit.
+ * percentage is reported, this isn't boost value. Smartshift power
+ * boost/shift is only when the percentage is more than 100.
+ */
+ if (metrics->StapmOpnLimit > 0)
+ *value = (metrics->ApuPower * 100) / metrics->StapmOpnLimit;
+ else
+ *value = 0;
+ break;
+ case METRICS_SS_DGPU_SHARE:
+ /* return the percentage of dGPU power with respect to dGPU's power limit.
+ * percentage is reported, this isn't boost value. Smartshift power
+ * boost/shift is only when the percentage is more than 100.
+ */
+ if ((metrics->dGpuPower > 0) &&
+ (metrics->StapmCurrentLimit > metrics->StapmOpnLimit))
+ *value = (metrics->dGpuPower * 100) /
+ (metrics->StapmCurrentLimit - metrics->StapmOpnLimit);
+ else
+ *value = 0;
+ break;
+ default:
+ *value = UINT_MAX;
+ break;
+ }
+
+ return ret;
+}
+
+static int smu_v13_0_4_get_current_clk_freq(struct smu_context *smu,
+ enum smu_clk_type clk_type,
+ uint32_t *value)
+{
+ MetricsMember_t member_type;
+
+ switch (clk_type) {
+ case SMU_SOCCLK:
+ member_type = METRICS_AVERAGE_SOCCLK;
+ break;
+ case SMU_VCLK:
+ member_type = METRICS_AVERAGE_VCLK;
+ break;
+ case SMU_DCLK:
+ member_type = METRICS_AVERAGE_DCLK;
+ break;
+ case SMU_MCLK:
+ member_type = METRICS_AVERAGE_UCLK;
+ break;
+ case SMU_FCLK:
+ return smu_cmn_send_smc_msg_with_param(smu,
+ SMU_MSG_GetFclkFrequency,
+ 0, value);
+ case SMU_GFXCLK:
+ case SMU_SCLK:
+ return smu_cmn_send_smc_msg_with_param(smu,
+ SMU_MSG_GetGfxclkFrequency,
+ 0, value);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return smu_v13_0_4_get_smu_metrics_data(smu, member_type, value);
+}
+
+static int smu_v13_0_4_get_dpm_freq_by_index(struct smu_context *smu,
+ enum smu_clk_type clk_type,
+ uint32_t dpm_level,
+ uint32_t *freq)
+{
+ DpmClocks_t *clk_table = smu->smu_table.clocks_table;
+
+ if (!clk_table || clk_type >= SMU_CLK_COUNT)
+ return -EINVAL;
+
+ switch (clk_type) {
+ case SMU_SOCCLK:
+ if (dpm_level >= clk_table->NumSocClkLevelsEnabled)
+ return -EINVAL;
+ *freq = clk_table->SocClocks[dpm_level];
+ break;
+ case SMU_VCLK:
+ if (dpm_level >= clk_table->VcnClkLevelsEnabled)
+ return -EINVAL;
+ *freq = clk_table->VClocks[dpm_level];
+ break;
+ case SMU_DCLK:
+ if (dpm_level >= clk_table->VcnClkLevelsEnabled)
+ return -EINVAL;
+ *freq = clk_table->DClocks[dpm_level];
+ break;
+ case SMU_UCLK:
+ case SMU_MCLK:
+ if (dpm_level >= clk_table->NumDfPstatesEnabled)
+ return -EINVAL;
+ *freq = clk_table->DfPstateTable[dpm_level].MemClk;
+ break;
+ case SMU_FCLK:
+ if (dpm_level >= clk_table->NumDfPstatesEnabled)
+ return -EINVAL;
+ *freq = clk_table->DfPstateTable[dpm_level].FClk;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int smu_v13_0_4_get_dpm_level_count(struct smu_context *smu,
+ enum smu_clk_type clk_type,
+ uint32_t *count)
+{
+ DpmClocks_t *clk_table = smu->smu_table.clocks_table;
+
+ switch (clk_type) {
+ case SMU_SOCCLK:
+ *count = clk_table->NumSocClkLevelsEnabled;
+ break;
+ case SMU_VCLK:
+ *count = clk_table->VcnClkLevelsEnabled;
+ break;
+ case SMU_DCLK:
+ *count = clk_table->VcnClkLevelsEnabled;
+ break;
+ case SMU_MCLK:
+ *count = clk_table->NumDfPstatesEnabled;
+ break;
+ case SMU_FCLK:
+ *count = clk_table->NumDfPstatesEnabled;
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int smu_v13_0_4_print_clk_levels(struct smu_context *smu,
+ enum smu_clk_type clk_type, char *buf)
+{
+ int i, size = 0, ret = 0;
+ uint32_t cur_value = 0, value = 0, count = 0;
+ uint32_t min, max;
+
+ smu_cmn_get_sysfs_buf(&buf, &size);
+
+ switch (clk_type) {
+ case SMU_OD_SCLK:
+ size += sysfs_emit_at(buf, size, "%s:\n", "OD_SCLK");
+ size += sysfs_emit_at(buf, size, "0: %10uMhz\n",
+ (smu->gfx_actual_hard_min_freq > 0) ? smu->gfx_actual_hard_min_freq : smu->gfx_default_hard_min_freq);
+ size += sysfs_emit_at(buf, size, "1: %10uMhz\n",
+ (smu->gfx_actual_soft_max_freq > 0) ? smu->gfx_actual_soft_max_freq : smu->gfx_default_soft_max_freq);
+ break;
+ case SMU_OD_RANGE:
+ size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE");
+ size += sysfs_emit_at(buf, size, "SCLK: %7uMhz %10uMhz\n",
+ smu->gfx_default_hard_min_freq,
+ smu->gfx_default_soft_max_freq);
+ break;
+ case SMU_SOCCLK:
+ case SMU_VCLK:
+ case SMU_DCLK:
+ case SMU_MCLK:
+ case SMU_FCLK:
+ ret = smu_v13_0_4_get_current_clk_freq(smu, clk_type, &cur_value);
+ if (ret)
+ break;
+
+ ret = smu_v13_0_4_get_dpm_level_count(smu, clk_type, &count);
+ if (ret)
+ break;
+
+ for (i = 0; i < count; i++) {
+ ret = smu_v13_0_4_get_dpm_freq_by_index(smu, clk_type, i, &value);
+ if (ret)
+ break;
+
+ size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", i, value,
+ cur_value == value ? "*" : "");
+ }
+ break;
+ case SMU_GFXCLK:
+ case SMU_SCLK:
+ ret = smu_v13_0_4_get_current_clk_freq(smu, clk_type, &cur_value);
+ if (ret)
+ break;
+ min = (smu->gfx_actual_hard_min_freq > 0) ? smu->gfx_actual_hard_min_freq : smu->gfx_default_hard_min_freq;
+ max = (smu->gfx_actual_soft_max_freq > 0) ? smu->gfx_actual_soft_max_freq : smu->gfx_default_soft_max_freq;
+ if (cur_value == max)
+ i = 2;
+ else if (cur_value == min)
+ i = 0;
+ else
+ i = 1;
+ size += sysfs_emit_at(buf, size, "0: %uMhz %s\n", min,
+ i == 0 ? "*" : "");
+ size += sysfs_emit_at(buf, size, "1: %uMhz %s\n",
+ i == 1 ? cur_value : 1100, /* UMD PSTATE GFXCLK 1100 */
+ i == 1 ? "*" : "");
+ size += sysfs_emit_at(buf, size, "2: %uMhz %s\n", max,
+ i == 2 ? "*" : "");
+ break;
+ default:
+ break;
+ }
+
+ return size;
+}
+
+static int smu_v13_0_4_read_sensor(struct smu_context *smu,
+ enum amd_pp_sensors sensor,
+ void *data, uint32_t *size)
+{
+ int ret = 0;
+
+ if (!data || !size)
+ return -EINVAL;
+
+ switch (sensor) {
+ case AMDGPU_PP_SENSOR_GPU_LOAD:
+ ret = smu_v13_0_4_get_smu_metrics_data(smu,
+ METRICS_AVERAGE_GFXACTIVITY,
+ (uint32_t *)data);
+ *size = 4;
+ break;
+ case AMDGPU_PP_SENSOR_GPU_POWER:
+ ret = smu_v13_0_4_get_smu_metrics_data(smu,
+ METRICS_AVERAGE_SOCKETPOWER,
+ (uint32_t *)data);
+ *size = 4;
+ break;
+ case AMDGPU_PP_SENSOR_EDGE_TEMP:
+ ret = smu_v13_0_4_get_smu_metrics_data(smu,
+ METRICS_TEMPERATURE_EDGE,
+ (uint32_t *)data);
+ *size = 4;
+ break;
+ case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
+ ret = smu_v13_0_4_get_smu_metrics_data(smu,
+ METRICS_TEMPERATURE_HOTSPOT,
+ (uint32_t *)data);
+ *size = 4;
+ break;
+ case AMDGPU_PP_SENSOR_GFX_MCLK:
+ ret = smu_v13_0_4_get_smu_metrics_data(smu,
+ METRICS_AVERAGE_UCLK,
+ (uint32_t *)data);
+ *(uint32_t *)data *= 100;
+ *size = 4;
+ break;
+ case AMDGPU_PP_SENSOR_GFX_SCLK:
+ ret = smu_v13_0_4_get_smu_metrics_data(smu,
+ METRICS_AVERAGE_GFXCLK,
+ (uint32_t *)data);
+ *(uint32_t *)data *= 100;
+ *size = 4;
+ break;
+ case AMDGPU_PP_SENSOR_VDDGFX:
+ ret = smu_v13_0_4_get_smu_metrics_data(smu,
+ METRICS_VOLTAGE_VDDGFX,
+ (uint32_t *)data);
+ *size = 4;
+ break;
+ case AMDGPU_PP_SENSOR_VDDNB:
+ ret = smu_v13_0_4_get_smu_metrics_data(smu,
+ METRICS_VOLTAGE_VDDSOC,
+ (uint32_t *)data);
+ *size = 4;
+ break;
+ case AMDGPU_PP_SENSOR_SS_APU_SHARE:
+ ret = smu_v13_0_4_get_smu_metrics_data(smu,
+ METRICS_SS_APU_SHARE,
+ (uint32_t *)data);
+ *size = 4;
+ break;
+ case AMDGPU_PP_SENSOR_SS_DGPU_SHARE:
+ ret = smu_v13_0_4_get_smu_metrics_data(smu,
+ METRICS_SS_DGPU_SHARE,
+ (uint32_t *)data);
+ *size = 4;
+ break;
+ default:
+ ret = -EOPNOTSUPP;
+ break;
+ }
+
+ return ret;
+}
+
+static int smu_v13_0_4_set_watermarks_table(struct smu_context *smu,
+ struct pp_smu_wm_range_sets *clock_ranges)
+{
+ int i;
+ int ret = 0;
+ Watermarks_t *table = smu->smu_table.watermarks_table;
+
+ if (!table || !clock_ranges)
+ return -EINVAL;
+
+ if (clock_ranges) {
+ if (clock_ranges->num_reader_wm_sets > NUM_WM_RANGES ||
+ clock_ranges->num_writer_wm_sets > NUM_WM_RANGES)
+ return -EINVAL;
+
+ for (i = 0; i < clock_ranges->num_reader_wm_sets; i++) {
+ table->WatermarkRow[WM_DCFCLK][i].MinClock =
+ clock_ranges->reader_wm_sets[i].min_drain_clk_mhz;
+ table->WatermarkRow[WM_DCFCLK][i].MaxClock =
+ clock_ranges->reader_wm_sets[i].max_drain_clk_mhz;
+ table->WatermarkRow[WM_DCFCLK][i].MinMclk =
+ clock_ranges->reader_wm_sets[i].min_fill_clk_mhz;
+ table->WatermarkRow[WM_DCFCLK][i].MaxMclk =
+ clock_ranges->reader_wm_sets[i].max_fill_clk_mhz;
+
+ table->WatermarkRow[WM_DCFCLK][i].WmSetting =
+ clock_ranges->reader_wm_sets[i].wm_inst;
+ }
+
+ for (i = 0; i < clock_ranges->num_writer_wm_sets; i++) {
+ table->WatermarkRow[WM_SOCCLK][i].MinClock =
+ clock_ranges->writer_wm_sets[i].min_fill_clk_mhz;
+ table->WatermarkRow[WM_SOCCLK][i].MaxClock =
+ clock_ranges->writer_wm_sets[i].max_fill_clk_mhz;
+ table->WatermarkRow[WM_SOCCLK][i].MinMclk =
+ clock_ranges->writer_wm_sets[i].min_drain_clk_mhz;
+ table->WatermarkRow[WM_SOCCLK][i].MaxMclk =
+ clock_ranges->writer_wm_sets[i].max_drain_clk_mhz;
+
+ table->WatermarkRow[WM_SOCCLK][i].WmSetting =
+ clock_ranges->writer_wm_sets[i].wm_inst;
+ }
+
+ smu->watermarks_bitmap |= WATERMARKS_EXIST;
+ }
+
+ /* pass data to smu controller */
+ if ((smu->watermarks_bitmap & WATERMARKS_EXIST) &&
+ !(smu->watermarks_bitmap & WATERMARKS_LOADED)) {
+ ret = smu_cmn_write_watermarks_table(smu);
+ if (ret) {
+ dev_err(smu->adev->dev, "Failed to update WMTABLE!");
+ return ret;
+ }
+ smu->watermarks_bitmap |= WATERMARKS_LOADED;
+ }
+
+ return 0;
+}
+
+static bool smu_v13_0_4_clk_dpm_is_enabled(struct smu_context *smu,
+ enum smu_clk_type clk_type)
+{
+ enum smu_feature_mask feature_id = 0;
+
+ switch (clk_type) {
+ case SMU_MCLK:
+ case SMU_UCLK:
+ case SMU_FCLK:
+ feature_id = SMU_FEATURE_DPM_FCLK_BIT;
+ break;
+ case SMU_GFXCLK:
+ case SMU_SCLK:
+ feature_id = SMU_FEATURE_DPM_GFXCLK_BIT;
+ break;
+ case SMU_SOCCLK:
+ feature_id = SMU_FEATURE_DPM_SOCCLK_BIT;
+ break;
+ case SMU_VCLK:
+ case SMU_DCLK:
+ feature_id = SMU_FEATURE_VCN_DPM_BIT;
+ break;
+ default:
+ return true;
+ }
+
+ return smu_cmn_feature_is_enabled(smu, feature_id);
+}
+
+static int smu_v13_0_4_get_dpm_ultimate_freq(struct smu_context *smu,
+ enum smu_clk_type clk_type,
+ uint32_t *min,
+ uint32_t *max)
+{
+ DpmClocks_t *clk_table = smu->smu_table.clocks_table;
+ uint32_t clock_limit;
+ uint32_t max_dpm_level, min_dpm_level;
+ int ret = 0;
+
+ if (!smu_v13_0_4_clk_dpm_is_enabled(smu, clk_type)) {
+ switch (clk_type) {
+ case SMU_MCLK:
+ case SMU_UCLK:
+ clock_limit = smu->smu_table.boot_values.uclk;
+ break;
+ case SMU_FCLK:
+ clock_limit = smu->smu_table.boot_values.fclk;
+ break;
+ case SMU_GFXCLK:
+ case SMU_SCLK:
+ clock_limit = smu->smu_table.boot_values.gfxclk;
+ break;
+ case SMU_SOCCLK:
+ clock_limit = smu->smu_table.boot_values.socclk;
+ break;
+ case SMU_VCLK:
+ clock_limit = smu->smu_table.boot_values.vclk;
+ break;
+ case SMU_DCLK:
+ clock_limit = smu->smu_table.boot_values.dclk;
+ break;
+ default:
+ clock_limit = 0;
+ break;
+ }
+
+ /* clock in Mhz unit */
+ if (min)
+ *min = clock_limit / 100;
+ if (max)
+ *max = clock_limit / 100;
+
+ return 0;
+ }
+
+ if (max) {
+ switch (clk_type) {
+ case SMU_GFXCLK:
+ case SMU_SCLK:
+ *max = clk_table->MaxGfxClk;
+ break;
+ case SMU_MCLK:
+ case SMU_UCLK:
+ case SMU_FCLK:
+ max_dpm_level = 0;
+ break;
+ case SMU_SOCCLK:
+ max_dpm_level = clk_table->NumSocClkLevelsEnabled - 1;
+ break;
+ case SMU_VCLK:
+ case SMU_DCLK:
+ max_dpm_level = clk_table->VcnClkLevelsEnabled - 1;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (clk_type != SMU_GFXCLK && clk_type != SMU_SCLK) {
+ ret = smu_v13_0_4_get_dpm_freq_by_index(smu, clk_type,
+ max_dpm_level,
+ max);
+ if (ret)
+ return ret;
+ }
+ }
+
+ if (min) {
+ switch (clk_type) {
+ case SMU_GFXCLK:
+ case SMU_SCLK:
+ *min = clk_table->MinGfxClk;
+ break;
+ case SMU_MCLK:
+ case SMU_UCLK:
+ case SMU_FCLK:
+ min_dpm_level = clk_table->NumDfPstatesEnabled - 1;
+ break;
+ case SMU_SOCCLK:
+ min_dpm_level = 0;
+ break;
+ case SMU_VCLK:
+ case SMU_DCLK:
+ min_dpm_level = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (clk_type != SMU_GFXCLK && clk_type != SMU_SCLK) {
+ ret = smu_v13_0_4_get_dpm_freq_by_index(smu, clk_type,
+ min_dpm_level,
+ min);
+ }
+ }
+
+ return ret;
+}
+
+static int smu_v13_0_4_set_soft_freq_limited_range(struct smu_context *smu,
+ enum smu_clk_type clk_type,
+ uint32_t min,
+ uint32_t max)
+{
+ enum smu_message_type msg_set_min, msg_set_max;
+ int ret = 0;
+
+ if (!smu_v13_0_4_clk_dpm_is_enabled(smu, clk_type))
+ return -EINVAL;
+
+ switch (clk_type) {
+ case SMU_GFXCLK:
+ case SMU_SCLK:
+ msg_set_min = SMU_MSG_SetHardMinGfxClk;
+ msg_set_max = SMU_MSG_SetSoftMaxGfxClk;
+ break;
+ case SMU_FCLK:
+ msg_set_min = SMU_MSG_SetHardMinFclkByFreq;
+ msg_set_max = SMU_MSG_SetSoftMaxFclkByFreq;
+ break;
+ case SMU_SOCCLK:
+ msg_set_min = SMU_MSG_SetHardMinSocclkByFreq;
+ msg_set_max = SMU_MSG_SetSoftMaxSocclkByFreq;
+ break;
+ case SMU_VCLK:
+ case SMU_DCLK:
+ msg_set_min = SMU_MSG_SetHardMinVcn;
+ msg_set_max = SMU_MSG_SetSoftMaxVcn;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = smu_cmn_send_smc_msg_with_param(smu, msg_set_min, min, NULL);
+ if (ret)
+ return ret;
+
+ return smu_cmn_send_smc_msg_with_param(smu, msg_set_max,
+ max, NULL);
+}
+
+static int smu_v13_0_4_force_clk_levels(struct smu_context *smu,
+ enum smu_clk_type clk_type,
+ uint32_t mask)
+{
+ uint32_t soft_min_level = 0, soft_max_level = 0;
+ uint32_t min_freq = 0, max_freq = 0;
+ int ret = 0;
+
+ soft_min_level = mask ? (ffs(mask) - 1) : 0;
+ soft_max_level = mask ? (fls(mask) - 1) : 0;
+
+ switch (clk_type) {
+ case SMU_SOCCLK:
+ case SMU_FCLK:
+ case SMU_VCLK:
+ case SMU_DCLK:
+ ret = smu_v13_0_4_get_dpm_freq_by_index(smu, clk_type, soft_min_level, &min_freq);
+ if (ret)
+ break;
+
+ ret = smu_v13_0_4_get_dpm_freq_by_index(smu, clk_type, soft_max_level, &max_freq);
+ if (ret)
+ break;
+
+ ret = smu_v13_0_4_set_soft_freq_limited_range(smu, clk_type, min_freq, max_freq);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static int smu_v13_0_4_set_performance_level(struct smu_context *smu,
+ enum amd_dpm_forced_level level)
+{
+ struct amdgpu_device *adev = smu->adev;
+ uint32_t sclk_min = 0, sclk_max = 0;
+ uint32_t fclk_min = 0, fclk_max = 0;
+ uint32_t socclk_min = 0, socclk_max = 0;
+ int ret = 0;
+
+ switch (level) {
+ case AMD_DPM_FORCED_LEVEL_HIGH:
+ smu_v13_0_4_get_dpm_ultimate_freq(smu, SMU_SCLK, NULL, &sclk_max);
+ smu_v13_0_4_get_dpm_ultimate_freq(smu, SMU_FCLK, NULL, &fclk_max);
+ smu_v13_0_4_get_dpm_ultimate_freq(smu, SMU_SOCCLK, NULL, &socclk_max);
+ sclk_min = sclk_max;
+ fclk_min = fclk_max;
+ socclk_min = socclk_max;
+ break;
+ case AMD_DPM_FORCED_LEVEL_LOW:
+ smu_v13_0_4_get_dpm_ultimate_freq(smu, SMU_SCLK, &sclk_min, NULL);
+ smu_v13_0_4_get_dpm_ultimate_freq(smu, SMU_FCLK, &fclk_min, NULL);
+ smu_v13_0_4_get_dpm_ultimate_freq(smu, SMU_SOCCLK, &socclk_min, NULL);
+ sclk_max = sclk_min;
+ fclk_max = fclk_min;
+ socclk_max = socclk_min;
+ break;
+ case AMD_DPM_FORCED_LEVEL_AUTO:
+ smu_v13_0_4_get_dpm_ultimate_freq(smu, SMU_SCLK, &sclk_min, &sclk_max);
+ smu_v13_0_4_get_dpm_ultimate_freq(smu, SMU_FCLK, &fclk_min, &fclk_max);
+ smu_v13_0_4_get_dpm_ultimate_freq(smu, SMU_SOCCLK, &socclk_min, &socclk_max);
+ break;
+ case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD:
+ case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK:
+ case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK:
+ case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK:
+ /* Temporarily do nothing since the optimal clocks haven't been provided yet */
+ break;
+ case AMD_DPM_FORCED_LEVEL_MANUAL:
+ case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT:
+ return 0;
+ default:
+ dev_err(adev->dev, "Invalid performance level %d\n", level);
+ return -EINVAL;
+ }
+
+ if (sclk_min && sclk_max) {
+ ret = smu_v13_0_4_set_soft_freq_limited_range(smu,
+ SMU_SCLK,
+ sclk_min,
+ sclk_max);
+ if (ret)
+ return ret;
+
+ smu->gfx_actual_hard_min_freq = sclk_min;
+ smu->gfx_actual_soft_max_freq = sclk_max;
+ }
+
+ if (fclk_min && fclk_max) {
+ ret = smu_v13_0_4_set_soft_freq_limited_range(smu,
+ SMU_FCLK,
+ fclk_min,
+ fclk_max);
+ if (ret)
+ return ret;
+ }
+
+ if (socclk_min && socclk_max) {
+ ret = smu_v13_0_4_set_soft_freq_limited_range(smu,
+ SMU_SOCCLK,
+ socclk_min,
+ socclk_max);
+ if (ret)
+ return ret;
+ }
+
+ return ret;
+}
+
+static int smu_v13_0_4_mode2_reset(struct smu_context *smu)
+{
+ return smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_GfxDeviceDriverReset,
+ SMU_RESET_MODE_2, NULL);
+}
+
+static int smu_v13_0_4_set_fine_grain_gfx_freq_parameters(struct smu_context *smu)
+{
+ DpmClocks_t *clk_table = smu->smu_table.clocks_table;
+
+ smu->gfx_default_hard_min_freq = clk_table->MinGfxClk;
+ smu->gfx_default_soft_max_freq = clk_table->MaxGfxClk;
+ smu->gfx_actual_hard_min_freq = 0;
+ smu->gfx_actual_soft_max_freq = 0;
+
+ return 0;
+}
+
+static const struct pptable_funcs smu_v13_0_4_ppt_funcs = {
+ .check_fw_status = smu_v13_0_check_fw_status,
+ .check_fw_version = smu_v13_0_check_fw_version,
+ .init_smc_tables = smu_v13_0_4_init_smc_tables,
+ .fini_smc_tables = smu_v13_0_4_fini_smc_tables,
+ .get_vbios_bootup_values = smu_v13_0_get_vbios_bootup_values,
+ .system_features_control = smu_v13_0_4_system_features_control,
+ .send_smc_msg_with_param = smu_cmn_send_smc_msg_with_param,
+ .send_smc_msg = smu_cmn_send_smc_msg,
+ .dpm_set_vcn_enable = smu_v13_0_set_vcn_enable,
+ .dpm_set_jpeg_enable = smu_v13_0_set_jpeg_enable,
+ .set_default_dpm_table = smu_v13_0_set_default_dpm_tables,
+ .read_sensor = smu_v13_0_4_read_sensor,
+ .is_dpm_running = smu_v13_0_4_is_dpm_running,
+ .set_watermarks_table = smu_v13_0_4_set_watermarks_table,
+ .get_gpu_metrics = smu_v13_0_4_get_gpu_metrics,
+ .get_enabled_mask = smu_cmn_get_enabled_mask,
+ .get_pp_feature_mask = smu_cmn_get_pp_feature_mask,
+ .set_driver_table_location = smu_v13_0_set_driver_table_location,
+ .gfx_off_control = smu_v13_0_gfx_off_control,
+ .post_init = smu_v13_0_4_post_smu_init,
+ .mode2_reset = smu_v13_0_4_mode2_reset,
+ .get_dpm_ultimate_freq = smu_v13_0_4_get_dpm_ultimate_freq,
+ .od_edit_dpm_table = smu_v13_0_od_edit_dpm_table,
+ .print_clk_levels = smu_v13_0_4_print_clk_levels,
+ .force_clk_levels = smu_v13_0_4_force_clk_levels,
+ .set_performance_level = smu_v13_0_4_set_performance_level,
+ .set_fine_grain_gfx_freq_parameters = smu_v13_0_4_set_fine_grain_gfx_freq_parameters,
+};
+
+void smu_v13_0_4_set_ppt_funcs(struct smu_context *smu)
+{
+ smu->ppt_funcs = &smu_v13_0_4_ppt_funcs;
+ smu->message_map = smu_v13_0_4_message_map;
+ smu->feature_map = smu_v13_0_4_feature_mask_map;
+ smu->table_map = smu_v13_0_4_table_map;
+ smu->is_apu = true;
+}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.h b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.h
new file mode 100644
index 000000000000..f0bd5d3ac4b6
--- /dev/null
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2022 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+#ifndef __SMU_V13_0_4_PPT_H__
+#define __SMU_V13_0_4_PPT_H__
+
+extern void smu_v13_0_4_set_ppt_funcs(struct smu_context *smu);
+
+#endif
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
new file mode 100644
index 000000000000..4e1861fb2c6a
--- /dev/null
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
@@ -0,0 +1,1597 @@
+/*
+ * Copyright 2021 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#define SWSMU_CODE_LAYER_L2
+
+#include <linux/firmware.h>
+#include <linux/pci.h>
+#include <linux/i2c.h>
+#include "amdgpu.h"
+#include "amdgpu_smu.h"
+#include "atomfirmware.h"
+#include "amdgpu_atomfirmware.h"
+#include "amdgpu_atombios.h"
+#include "smu_v13_0.h"
+#include "smu13_driver_if_v13_0_7.h"
+#include "soc15_common.h"
+#include "atom.h"
+#include "smu_v13_0_7_ppt.h"
+#include "smu_v13_0_7_pptable.h"
+#include "smu_v13_0_7_ppsmc.h"
+#include "nbio/nbio_4_3_0_offset.h"
+#include "nbio/nbio_4_3_0_sh_mask.h"
+#include "mp/mp_13_0_0_offset.h"
+#include "mp/mp_13_0_0_sh_mask.h"
+
+#include "asic_reg/mp/mp_13_0_0_sh_mask.h"
+#include "smu_cmn.h"
+#include "amdgpu_ras.h"
+
+/*
+ * DO NOT use these for err/warn/info/debug messages.
+ * Use dev_err, dev_warn, dev_info and dev_dbg instead.
+ * They are more MGPU friendly.
+ */
+#undef pr_err
+#undef pr_warn
+#undef pr_info
+#undef pr_debug
+
+#define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c))
+
+#define FEATURE_MASK(feature) (1ULL << feature)
+#define SMC_DPM_FEATURE ( \
+ FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT) | \
+ FEATURE_MASK(FEATURE_DPM_UCLK_BIT) | \
+ FEATURE_MASK(FEATURE_DPM_LINK_BIT) | \
+ FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT) | \
+ FEATURE_MASK(FEATURE_DPM_FCLK_BIT) | \
+ FEATURE_MASK(FEATURE_DPM_MP0CLK_BIT))
+
+#define smnMP1_FIRMWARE_FLAGS_SMU_13_0_7 0x3b10028
+
+#define MP0_MP1_DATA_REGION_SIZE_COMBOPPTABLE 0x4000
+
+static struct cmn2asic_msg_mapping smu_v13_0_7_message_map[SMU_MSG_MAX_COUNT] = {
+ MSG_MAP(TestMessage, PPSMC_MSG_TestMessage, 1),
+ MSG_MAP(GetSmuVersion, PPSMC_MSG_GetSmuVersion, 1),
+ MSG_MAP(GetDriverIfVersion, PPSMC_MSG_GetDriverIfVersion, 1),
+ MSG_MAP(SetAllowedFeaturesMaskLow, PPSMC_MSG_SetAllowedFeaturesMaskLow, 0),
+ MSG_MAP(SetAllowedFeaturesMaskHigh, PPSMC_MSG_SetAllowedFeaturesMaskHigh, 0),
+ MSG_MAP(EnableAllSmuFeatures, PPSMC_MSG_EnableAllSmuFeatures, 0),
+ MSG_MAP(DisableAllSmuFeatures, PPSMC_MSG_DisableAllSmuFeatures, 0),
+ MSG_MAP(EnableSmuFeaturesLow, PPSMC_MSG_EnableSmuFeaturesLow, 1),
+ MSG_MAP(EnableSmuFeaturesHigh, PPSMC_MSG_EnableSmuFeaturesHigh, 1),
+ MSG_MAP(DisableSmuFeaturesLow, PPSMC_MSG_DisableSmuFeaturesLow, 1),
+ MSG_MAP(DisableSmuFeaturesHigh, PPSMC_MSG_DisableSmuFeaturesHigh, 1),
+ MSG_MAP(GetEnabledSmuFeaturesLow, PPSMC_MSG_GetRunningSmuFeaturesLow, 1),
+ MSG_MAP(GetEnabledSmuFeaturesHigh, PPSMC_MSG_GetRunningSmuFeaturesHigh, 1),
+ MSG_MAP(SetWorkloadMask, PPSMC_MSG_SetWorkloadMask, 1),
+ MSG_MAP(SetPptLimit, PPSMC_MSG_SetPptLimit, 0),
+ MSG_MAP(SetDriverDramAddrHigh, PPSMC_MSG_SetDriverDramAddrHigh, 1),
+ MSG_MAP(SetDriverDramAddrLow, PPSMC_MSG_SetDriverDramAddrLow, 1),
+ MSG_MAP(SetToolsDramAddrHigh, PPSMC_MSG_SetToolsDramAddrHigh, 0),
+ MSG_MAP(SetToolsDramAddrLow, PPSMC_MSG_SetToolsDramAddrLow, 0),
+ MSG_MAP(TransferTableSmu2Dram, PPSMC_MSG_TransferTableSmu2Dram, 1),
+ MSG_MAP(TransferTableDram2Smu, PPSMC_MSG_TransferTableDram2Smu, 0),
+ MSG_MAP(UseDefaultPPTable, PPSMC_MSG_UseDefaultPPTable, 0),
+ MSG_MAP(RunDcBtc, PPSMC_MSG_RunDcBtc, 0),
+ MSG_MAP(EnterBaco, PPSMC_MSG_EnterBaco, 0),
+ MSG_MAP(SetSoftMinByFreq, PPSMC_MSG_SetSoftMinByFreq, 1),
+ MSG_MAP(SetSoftMaxByFreq, PPSMC_MSG_SetSoftMaxByFreq, 1),
+ MSG_MAP(SetHardMinByFreq, PPSMC_MSG_SetHardMinByFreq, 1),
+ MSG_MAP(SetHardMaxByFreq, PPSMC_MSG_SetHardMaxByFreq, 0),
+ MSG_MAP(GetMinDpmFreq, PPSMC_MSG_GetMinDpmFreq, 1),
+ MSG_MAP(GetMaxDpmFreq, PPSMC_MSG_GetMaxDpmFreq, 1),
+ MSG_MAP(GetDpmFreqByIndex, PPSMC_MSG_GetDpmFreqByIndex, 1),
+ MSG_MAP(PowerUpVcn, PPSMC_MSG_PowerUpVcn, 0),
+ MSG_MAP(PowerDownVcn, PPSMC_MSG_PowerDownVcn, 0),
+ MSG_MAP(PowerUpJpeg, PPSMC_MSG_PowerUpJpeg, 0),
+ MSG_MAP(PowerDownJpeg, PPSMC_MSG_PowerDownJpeg, 0),
+ MSG_MAP(GetDcModeMaxDpmFreq, PPSMC_MSG_GetDcModeMaxDpmFreq, 1),
+ MSG_MAP(OverridePcieParameters, PPSMC_MSG_OverridePcieParameters, 0),
+ MSG_MAP(DramLogSetDramAddrHigh, PPSMC_MSG_DramLogSetDramAddrHigh, 0),
+ MSG_MAP(DramLogSetDramAddrLow, PPSMC_MSG_DramLogSetDramAddrLow, 0),
+ MSG_MAP(DramLogSetDramSize, PPSMC_MSG_DramLogSetDramSize, 0),
+ MSG_MAP(AllowGfxOff, PPSMC_MSG_AllowGfxOff, 0),
+ MSG_MAP(DisallowGfxOff, PPSMC_MSG_DisallowGfxOff, 0),
+};
+
+static struct cmn2asic_mapping smu_v13_0_7_clk_map[SMU_CLK_COUNT] = {
+ CLK_MAP(GFXCLK, PPCLK_GFXCLK),
+ CLK_MAP(SCLK, PPCLK_GFXCLK),
+ CLK_MAP(SOCCLK, PPCLK_SOCCLK),
+ CLK_MAP(FCLK, PPCLK_FCLK),
+ CLK_MAP(UCLK, PPCLK_UCLK),
+ CLK_MAP(MCLK, PPCLK_UCLK),
+ CLK_MAP(VCLK, PPCLK_VCLK_0),
+ CLK_MAP(VCLK1, PPCLK_VCLK_1),
+ CLK_MAP(DCLK, PPCLK_DCLK_0),
+ CLK_MAP(DCLK1, PPCLK_DCLK_1),
+};
+
+static struct cmn2asic_mapping smu_v13_0_7_feature_mask_map[SMU_FEATURE_COUNT] = {
+ FEA_MAP(FW_DATA_READ),
+ FEA_MAP(DPM_GFXCLK),
+ FEA_MAP(DPM_GFX_POWER_OPTIMIZER),
+ FEA_MAP(DPM_UCLK),
+ FEA_MAP(DPM_FCLK),
+ FEA_MAP(DPM_SOCCLK),
+ FEA_MAP(DPM_MP0CLK),
+ FEA_MAP(DPM_LINK),
+ FEA_MAP(DPM_DCN),
+ FEA_MAP(VMEMP_SCALING),
+ FEA_MAP(VDDIO_MEM_SCALING),
+ FEA_MAP(DS_GFXCLK),
+ FEA_MAP(DS_SOCCLK),
+ FEA_MAP(DS_FCLK),
+ FEA_MAP(DS_LCLK),
+ FEA_MAP(DS_DCFCLK),
+ FEA_MAP(DS_UCLK),
+ FEA_MAP(GFX_ULV),
+ FEA_MAP(FW_DSTATE),
+ FEA_MAP(GFXOFF),
+ FEA_MAP(BACO),
+ FEA_MAP(MM_DPM),
+ FEA_MAP(SOC_MPCLK_DS),
+ FEA_MAP(BACO_MPCLK_DS),
+ FEA_MAP(THROTTLERS),
+ FEA_MAP(SMARTSHIFT),
+ FEA_MAP(GTHR),
+ FEA_MAP(ACDC),
+ FEA_MAP(VR0HOT),
+ FEA_MAP(FW_CTF),
+ FEA_MAP(FAN_CONTROL),
+ FEA_MAP(GFX_DCS),
+ FEA_MAP(GFX_READ_MARGIN),
+ FEA_MAP(LED_DISPLAY),
+ FEA_MAP(GFXCLK_SPREAD_SPECTRUM),
+ FEA_MAP(OUT_OF_BAND_MONITOR),
+ FEA_MAP(OPTIMIZED_VMIN),
+ FEA_MAP(GFX_IMU),
+ FEA_MAP(BOOT_TIME_CAL),
+ FEA_MAP(GFX_PCC_DFLL),
+ FEA_MAP(SOC_CG),
+ FEA_MAP(DF_CSTATE),
+ FEA_MAP(GFX_EDC),
+ FEA_MAP(BOOT_POWER_OPT),
+ FEA_MAP(CLOCK_POWER_DOWN_BYPASS),
+ FEA_MAP(DS_VCN),
+ FEA_MAP(BACO_CG),
+ FEA_MAP(MEM_TEMP_READ),
+ FEA_MAP(ATHUB_MMHUB_PG),
+ FEA_MAP(SOC_PCC),
+};
+
+static struct cmn2asic_mapping smu_v13_0_7_table_map[SMU_TABLE_COUNT] = {
+ TAB_MAP(PPTABLE),
+ TAB_MAP(WATERMARKS),
+ TAB_MAP(AVFS_PSM_DEBUG),
+ TAB_MAP(PMSTATUSLOG),
+ TAB_MAP(SMU_METRICS),
+ TAB_MAP(DRIVER_SMU_CONFIG),
+ TAB_MAP(ACTIVITY_MONITOR_COEFF),
+ [SMU_TABLE_COMBO_PPTABLE] = {1, TABLE_COMBO_PPTABLE},
+};
+
+static struct cmn2asic_mapping smu_v13_0_7_pwr_src_map[SMU_POWER_SOURCE_COUNT] = {
+ PWR_MAP(AC),
+ PWR_MAP(DC),
+};
+
+static struct cmn2asic_mapping smu_v13_0_7_workload_map[PP_SMC_POWER_PROFILE_COUNT] = {
+ WORKLOAD_MAP(PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT, WORKLOAD_PPLIB_DEFAULT_BIT),
+ WORKLOAD_MAP(PP_SMC_POWER_PROFILE_FULLSCREEN3D, WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT),
+ WORKLOAD_MAP(PP_SMC_POWER_PROFILE_POWERSAVING, WORKLOAD_PPLIB_POWER_SAVING_BIT),
+ WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VIDEO, WORKLOAD_PPLIB_VIDEO_BIT),
+ WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VR, WORKLOAD_PPLIB_VR_BIT),
+ WORKLOAD_MAP(PP_SMC_POWER_PROFILE_COMPUTE, WORKLOAD_PPLIB_COMPUTE_BIT),
+ WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CUSTOM, WORKLOAD_PPLIB_CUSTOM_BIT),
+ WORKLOAD_MAP(PP_SMC_POWER_PROFILE_WINDOW3D, WORKLOAD_PPLIB_WINDOW_3D_BIT),
+};
+
+static const uint8_t smu_v13_0_7_throttler_map[] = {
+ [THROTTLER_PPT0_BIT] = (SMU_THROTTLER_PPT0_BIT),
+ [THROTTLER_PPT1_BIT] = (SMU_THROTTLER_PPT1_BIT),
+ [THROTTLER_PPT2_BIT] = (SMU_THROTTLER_PPT2_BIT),
+ [THROTTLER_PPT3_BIT] = (SMU_THROTTLER_PPT3_BIT),
+ [THROTTLER_TDC_GFX_BIT] = (SMU_THROTTLER_TDC_GFX_BIT),
+ [THROTTLER_TDC_SOC_BIT] = (SMU_THROTTLER_TDC_SOC_BIT),
+ [THROTTLER_TEMP_EDGE_BIT] = (SMU_THROTTLER_TEMP_EDGE_BIT),
+ [THROTTLER_TEMP_HOTSPOT_BIT] = (SMU_THROTTLER_TEMP_HOTSPOT_BIT),
+ [THROTTLER_TEMP_MEM_BIT] = (SMU_THROTTLER_TEMP_MEM_BIT),
+ [THROTTLER_TEMP_VR_GFX_BIT] = (SMU_THROTTLER_TEMP_VR_GFX_BIT),
+ [THROTTLER_TEMP_VR_SOC_BIT] = (SMU_THROTTLER_TEMP_VR_SOC_BIT),
+ [THROTTLER_TEMP_VR_MEM0_BIT] = (SMU_THROTTLER_TEMP_VR_MEM0_BIT),
+ [THROTTLER_TEMP_VR_MEM1_BIT] = (SMU_THROTTLER_TEMP_VR_MEM1_BIT),
+ [THROTTLER_TEMP_LIQUID0_BIT] = (SMU_THROTTLER_TEMP_LIQUID0_BIT),
+ [THROTTLER_TEMP_LIQUID1_BIT] = (SMU_THROTTLER_TEMP_LIQUID1_BIT),
+ [THROTTLER_GFX_APCC_PLUS_BIT] = (SMU_THROTTLER_APCC_BIT),
+ [THROTTLER_FIT_BIT] = (SMU_THROTTLER_FIT_BIT),
+};
+
+static int
+smu_v13_0_7_get_allowed_feature_mask(struct smu_context *smu,
+ uint32_t *feature_mask, uint32_t num)
+{
+ struct amdgpu_device *adev = smu->adev;
+
+ if (num > 2)
+ return -EINVAL;
+
+ memset(feature_mask, 0, sizeof(uint32_t) * num);
+
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_FW_DATA_READ_BIT);
+
+ if (adev->pm.pp_feature & PP_SCLK_DPM_MASK) {
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT);
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_GFX_IMU_BIT);
+ }
+
+ if (adev->pm.pp_feature & PP_MCLK_DPM_MASK) {
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_UCLK_BIT);
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_FCLK_BIT);
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_VMEMP_SCALING_BIT);
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_VDDIO_MEM_SCALING_BIT);
+ }
+
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT);
+
+ if (adev->pm.pp_feature & PP_PCIE_DPM_MASK)
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_LINK_BIT);
+
+ if (adev->pm.pp_feature & PP_SCLK_DEEP_SLEEP_MASK)
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DS_GFXCLK_BIT);
+
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DS_LCLK_BIT);
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_MP0CLK_BIT);
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_MM_DPM_BIT);
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DS_VCN_BIT);
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DS_FCLK_BIT);
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DF_CSTATE_BIT);
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_THROTTLERS_BIT);
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_VR0HOT_BIT);
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_FW_CTF_BIT);
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_FAN_CONTROL_BIT);
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DS_SOCCLK_BIT);
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_GFXCLK_SPREAD_SPECTRUM_BIT);
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_MEM_TEMP_READ_BIT);
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_FW_DSTATE_BIT);
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_SOC_MPCLK_DS_BIT);
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_BACO_MPCLK_DS_BIT);
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_GFX_PCC_DFLL_BIT);
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_SOC_CG_BIT);
+
+ if (adev->pm.pp_feature & PP_DCEFCLK_DPM_MASK)
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_DCN_BIT);
+
+ if ((adev->pg_flags & AMD_PG_SUPPORT_ATHUB) &&
+ (adev->pg_flags & AMD_PG_SUPPORT_MMHUB))
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_ATHUB_MMHUB_PG_BIT);
+
+ return 0;
+}
+
+static int smu_v13_0_7_check_powerplay_table(struct smu_context *smu)
+{
+ struct smu_table_context *table_context = &smu->smu_table;
+ struct smu_13_0_7_powerplay_table *powerplay_table =
+ table_context->power_play_table;
+ struct smu_baco_context *smu_baco = &smu->smu_baco;
+
+ if (powerplay_table->platform_caps & SMU_13_0_7_PP_PLATFORM_CAP_HARDWAREDC)
+ smu->dc_controlled_by_gpio = true;
+
+ if (powerplay_table->platform_caps & SMU_13_0_7_PP_PLATFORM_CAP_BACO ||
+ powerplay_table->platform_caps & SMU_13_0_7_PP_PLATFORM_CAP_MACO)
+ smu_baco->platform_support = true;
+
+ table_context->thermal_controller_type =
+ powerplay_table->thermal_controller_type;
+
+ /*
+ * Instead of having its own buffer space and get overdrive_table copied,
+ * smu->od_settings just points to the actual overdrive_table
+ */
+ smu->od_settings = &powerplay_table->overdrive_table;
+
+ return 0;
+}
+
+static int smu_v13_0_7_store_powerplay_table(struct smu_context *smu)
+{
+ struct smu_table_context *table_context = &smu->smu_table;
+ struct smu_13_0_7_powerplay_table *powerplay_table =
+ table_context->power_play_table;
+ struct amdgpu_device *adev = smu->adev;
+
+ if (adev->pdev->device == 0x51)
+ powerplay_table->smc_pptable.SkuTable.DebugOverrides |= 0x00000080;
+
+ memcpy(table_context->driver_pptable, &powerplay_table->smc_pptable,
+ sizeof(PPTable_t));
+
+ return 0;
+}
+
+static int smu_v13_0_7_check_fw_status(struct smu_context *smu)
+{
+ struct amdgpu_device *adev = smu->adev;
+ uint32_t mp1_fw_flags;
+
+ mp1_fw_flags = RREG32_PCIE(MP1_Public |
+ (smnMP1_FIRMWARE_FLAGS_SMU_13_0_7 & 0xffffffff));
+
+ if ((mp1_fw_flags & MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED_MASK) >>
+ MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED__SHIFT)
+ return 0;
+
+ return -EIO;
+}
+
+#ifndef atom_smc_dpm_info_table_13_0_7
+struct atom_smc_dpm_info_table_13_0_7
+{
+ struct atom_common_table_header table_header;
+ BoardTable_t BoardTable;
+};
+#endif
+
+static int smu_v13_0_7_append_powerplay_table(struct smu_context *smu)
+{
+ struct smu_table_context *table_context = &smu->smu_table;
+
+ PPTable_t *smc_pptable = table_context->driver_pptable;
+
+ struct atom_smc_dpm_info_table_13_0_7 *smc_dpm_table;
+
+ BoardTable_t *BoardTable = &smc_pptable->BoardTable;
+
+ int index, ret;
+
+ index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
+ smc_dpm_info);
+
+ ret = amdgpu_atombios_get_data_table(smu->adev, index, NULL, NULL, NULL,
+ (uint8_t **)&smc_dpm_table);
+ if (ret)
+ return ret;
+
+ memcpy(BoardTable, &smc_dpm_table->BoardTable, sizeof(BoardTable_t));
+
+ return 0;
+}
+
+
+static int smu_v13_0_7_setup_pptable(struct smu_context *smu)
+{
+ struct smu_table_context *smu_table = &smu->smu_table;
+ void *combo_pptable = smu_table->combo_pptable;
+ struct amdgpu_device *adev = smu->adev;
+ int ret = 0;
+
+ /*
+ * With SCPM enabled, the pptable used will be signed. It cannot
+ * be used directly by driver. To get the raw pptable, we need to
+ * rely on the combo pptable(and its revelant SMU message).
+ */
+ if (adev->scpm_enabled) {
+ ret = smu_cmn_get_combo_pptable(smu);
+ if (ret)
+ return ret;
+
+ smu->smu_table.power_play_table = combo_pptable;
+ smu->smu_table.power_play_table_size = sizeof(struct smu_13_0_7_powerplay_table);
+ } else {
+ ret = smu_v13_0_setup_pptable(smu);
+ if (ret)
+ return ret;
+ }
+
+ ret = smu_v13_0_7_store_powerplay_table(smu);
+ if (ret)
+ return ret;
+
+ /*
+ * With SCPM enabled, the operation below will be handled
+ * by PSP. Driver involvment is unnecessary and useless.
+ */
+ if (!adev->scpm_enabled) {
+ ret = smu_v13_0_7_append_powerplay_table(smu);
+ if (ret)
+ return ret;
+ }
+
+ ret = smu_v13_0_7_check_powerplay_table(smu);
+ if (ret)
+ return ret;
+
+ return ret;
+}
+
+static int smu_v13_0_7_tables_init(struct smu_context *smu)
+{
+ struct smu_table_context *smu_table = &smu->smu_table;
+ struct smu_table *tables = smu_table->tables;
+
+ SMU_TABLE_INIT(tables, SMU_TABLE_PPTABLE, sizeof(PPTable_t),
+ PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
+
+ SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, sizeof(Watermarks_t),
+ PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
+ SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetricsExternal_t),
+ PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
+ SMU_TABLE_INIT(tables, SMU_TABLE_I2C_COMMANDS, sizeof(SwI2cRequest_t),
+ PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
+ SMU_TABLE_INIT(tables, SMU_TABLE_OVERDRIVE, sizeof(OverDriveTable_t),
+ PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
+ SMU_TABLE_INIT(tables, SMU_TABLE_PMSTATUSLOG, SMU13_TOOL_SIZE,
+ PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
+ SMU_TABLE_INIT(tables, SMU_TABLE_ACTIVITY_MONITOR_COEFF,
+ sizeof(DpmActivityMonitorCoeffIntExternal_t), PAGE_SIZE,
+ AMDGPU_GEM_DOMAIN_VRAM);
+ SMU_TABLE_INIT(tables, SMU_TABLE_COMBO_PPTABLE, MP0_MP1_DATA_REGION_SIZE_COMBOPPTABLE,
+ PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
+
+ smu_table->metrics_table = kzalloc(sizeof(SmuMetricsExternal_t), GFP_KERNEL);
+ if (!smu_table->metrics_table)
+ goto err0_out;
+ smu_table->metrics_time = 0;
+
+ smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v1_3);
+ smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL);
+ if (!smu_table->gpu_metrics_table)
+ goto err1_out;
+
+ smu_table->watermarks_table = kzalloc(sizeof(Watermarks_t), GFP_KERNEL);
+ if (!smu_table->watermarks_table)
+ goto err2_out;
+
+ return 0;
+
+err2_out:
+ kfree(smu_table->gpu_metrics_table);
+err1_out:
+ kfree(smu_table->metrics_table);
+err0_out:
+ return -ENOMEM;
+}
+
+static int smu_v13_0_7_allocate_dpm_context(struct smu_context *smu)
+{
+ struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
+
+ smu_dpm->dpm_context = kzalloc(sizeof(struct smu_13_0_dpm_context),
+ GFP_KERNEL);
+ if (!smu_dpm->dpm_context)
+ return -ENOMEM;
+
+ smu_dpm->dpm_context_size = sizeof(struct smu_13_0_dpm_context);
+
+ return 0;
+}
+
+static int smu_v13_0_7_init_smc_tables(struct smu_context *smu)
+{
+ int ret = 0;
+
+ ret = smu_v13_0_7_tables_init(smu);
+ if (ret)
+ return ret;
+
+ ret = smu_v13_0_7_allocate_dpm_context(smu);
+ if (ret)
+ return ret;
+
+ return smu_v13_0_init_smc_tables(smu);
+}
+
+static int smu_v13_0_7_set_default_dpm_table(struct smu_context *smu)
+{
+ struct smu_13_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context;
+ PPTable_t *driver_ppt = smu->smu_table.driver_pptable;
+ SkuTable_t *skutable = &driver_ppt->SkuTable;
+ struct smu_13_0_dpm_table *dpm_table;
+ struct smu_13_0_pcie_table *pcie_table;
+ uint32_t link_level;
+ int ret = 0;
+
+ /* socclk dpm table setup */
+ dpm_table = &dpm_context->dpm_tables.soc_table;
+ if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) {
+ ret = smu_v13_0_set_single_dpm_table(smu,
+ SMU_SOCCLK,
+ dpm_table);
+ if (ret)
+ return ret;
+ } else {
+ dpm_table->count = 1;
+ dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.socclk / 100;
+ dpm_table->dpm_levels[0].enabled = true;
+ dpm_table->min = dpm_table->dpm_levels[0].value;
+ dpm_table->max = dpm_table->dpm_levels[0].value;
+ }
+
+ /* gfxclk dpm table setup */
+ dpm_table = &dpm_context->dpm_tables.gfx_table;
+ if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT)) {
+ ret = smu_v13_0_set_single_dpm_table(smu,
+ SMU_GFXCLK,
+ dpm_table);
+ if (ret)
+ return ret;
+ } else {
+ dpm_table->count = 1;
+ dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100;
+ dpm_table->dpm_levels[0].enabled = true;
+ dpm_table->min = dpm_table->dpm_levels[0].value;
+ dpm_table->max = dpm_table->dpm_levels[0].value;
+ }
+
+ /* uclk dpm table setup */
+ dpm_table = &dpm_context->dpm_tables.uclk_table;
+ if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) {
+ ret = smu_v13_0_set_single_dpm_table(smu,
+ SMU_UCLK,
+ dpm_table);
+ if (ret)
+ return ret;
+ } else {
+ dpm_table->count = 1;
+ dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.uclk / 100;
+ dpm_table->dpm_levels[0].enabled = true;
+ dpm_table->min = dpm_table->dpm_levels[0].value;
+ dpm_table->max = dpm_table->dpm_levels[0].value;
+ }
+
+ /* fclk dpm table setup */
+ dpm_table = &dpm_context->dpm_tables.fclk_table;
+ if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_FCLK_BIT)) {
+ ret = smu_v13_0_set_single_dpm_table(smu,
+ SMU_FCLK,
+ dpm_table);
+ if (ret)
+ return ret;
+ } else {
+ dpm_table->count = 1;
+ dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.fclk / 100;
+ dpm_table->dpm_levels[0].enabled = true;
+ dpm_table->min = dpm_table->dpm_levels[0].value;
+ dpm_table->max = dpm_table->dpm_levels[0].value;
+ }
+
+ /* vclk dpm table setup */
+ dpm_table = &dpm_context->dpm_tables.vclk_table;
+ if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_VCLK_BIT)) {
+ ret = smu_v13_0_set_single_dpm_table(smu,
+ SMU_VCLK,
+ dpm_table);
+ if (ret)
+ return ret;
+ } else {
+ dpm_table->count = 1;
+ dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.vclk / 100;
+ dpm_table->dpm_levels[0].enabled = true;
+ dpm_table->min = dpm_table->dpm_levels[0].value;
+ dpm_table->max = dpm_table->dpm_levels[0].value;
+ }
+
+ /* dclk dpm table setup */
+ dpm_table = &dpm_context->dpm_tables.dclk_table;
+ if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_DCLK_BIT)) {
+ ret = smu_v13_0_set_single_dpm_table(smu,
+ SMU_DCLK,
+ dpm_table);
+ if (ret)
+ return ret;
+ } else {
+ dpm_table->count = 1;
+ dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dclk / 100;
+ dpm_table->dpm_levels[0].enabled = true;
+ dpm_table->min = dpm_table->dpm_levels[0].value;
+ dpm_table->max = dpm_table->dpm_levels[0].value;
+ }
+
+ /* lclk dpm table setup */
+ pcie_table = &dpm_context->dpm_tables.pcie_table;
+ pcie_table->num_of_link_levels = 0;
+ for (link_level = 0; link_level < NUM_LINK_LEVELS; link_level++) {
+ if (!skutable->PcieGenSpeed[link_level] &&
+ !skutable->PcieLaneCount[link_level] &&
+ !skutable->LclkFreq[link_level])
+ continue;
+
+ pcie_table->pcie_gen[pcie_table->num_of_link_levels] =
+ skutable->PcieGenSpeed[link_level];
+ pcie_table->pcie_lane[pcie_table->num_of_link_levels] =
+ skutable->PcieLaneCount[link_level];
+ pcie_table->clk_freq[pcie_table->num_of_link_levels] =
+ skutable->LclkFreq[link_level];
+ pcie_table->num_of_link_levels++;
+ }
+
+ return 0;
+}
+
+static bool smu_v13_0_7_is_dpm_running(struct smu_context *smu)
+{
+ int ret = 0;
+ uint64_t feature_enabled;
+
+ ret = smu_cmn_get_enabled_mask(smu, &feature_enabled);
+ if (ret)
+ return false;
+
+ return !!(feature_enabled & SMC_DPM_FEATURE);
+}
+
+static void smu_v13_0_7_dump_pptable(struct smu_context *smu)
+{
+ struct smu_table_context *table_context = &smu->smu_table;
+ PPTable_t *pptable = table_context->driver_pptable;
+ SkuTable_t *skutable = &pptable->SkuTable;
+
+ dev_info(smu->adev->dev, "Dumped PPTable:\n");
+
+ dev_info(smu->adev->dev, "Version = 0x%08x\n", skutable->Version);
+ dev_info(smu->adev->dev, "FeaturesToRun[0] = 0x%08x\n", skutable->FeaturesToRun[0]);
+ dev_info(smu->adev->dev, "FeaturesToRun[1] = 0x%08x\n", skutable->FeaturesToRun[1]);
+}
+
+static uint32_t smu_v13_0_7_get_throttler_status(SmuMetrics_t *metrics)
+{
+ uint32_t throttler_status = 0;
+ int i;
+
+ for (i = 0; i < THROTTLER_COUNT; i++)
+ throttler_status |=
+ (metrics->ThrottlingPercentage[i] ? 1U << i : 0);
+
+ return throttler_status;
+}
+
+#define SMU_13_0_7_BUSY_THRESHOLD 15
+static int smu_v13_0_7_get_smu_metrics_data(struct smu_context *smu,
+ MetricsMember_t member,
+ uint32_t *value)
+{
+ struct smu_table_context *smu_table= &smu->smu_table;
+ SmuMetrics_t *metrics =
+ &(((SmuMetricsExternal_t *)(smu_table->metrics_table))->SmuMetrics);
+ int ret = 0;
+
+ ret = smu_cmn_get_metrics_table(smu,
+ NULL,
+ false);
+ if (ret)
+ return ret;
+
+ switch (member) {
+ case METRICS_CURR_GFXCLK:
+ *value = metrics->CurrClock[PPCLK_GFXCLK];
+ break;
+ case METRICS_CURR_SOCCLK:
+ *value = metrics->CurrClock[PPCLK_SOCCLK];
+ break;
+ case METRICS_CURR_UCLK:
+ *value = metrics->CurrClock[PPCLK_UCLK];
+ break;
+ case METRICS_CURR_VCLK:
+ *value = metrics->CurrClock[PPCLK_VCLK_0];
+ break;
+ case METRICS_CURR_VCLK1:
+ *value = metrics->CurrClock[PPCLK_VCLK_1];
+ break;
+ case METRICS_CURR_DCLK:
+ *value = metrics->CurrClock[PPCLK_DCLK_0];
+ break;
+ case METRICS_CURR_DCLK1:
+ *value = metrics->CurrClock[PPCLK_DCLK_1];
+ break;
+ case METRICS_CURR_FCLK:
+ *value = metrics->CurrClock[PPCLK_FCLK];
+ break;
+ case METRICS_AVERAGE_GFXCLK:
+ *value = metrics->AverageGfxclkFrequencyPreDs;
+ break;
+ case METRICS_AVERAGE_FCLK:
+ if (metrics->AverageUclkActivity <= SMU_13_0_7_BUSY_THRESHOLD)
+ *value = metrics->AverageFclkFrequencyPostDs;
+ else
+ *value = metrics->AverageFclkFrequencyPreDs;
+ break;
+ case METRICS_AVERAGE_UCLK:
+ if (metrics->AverageUclkActivity <= SMU_13_0_7_BUSY_THRESHOLD)
+ *value = metrics->AverageMemclkFrequencyPostDs;
+ else
+ *value = metrics->AverageMemclkFrequencyPreDs;
+ break;
+ case METRICS_AVERAGE_VCLK:
+ *value = metrics->AverageVclk0Frequency;
+ break;
+ case METRICS_AVERAGE_DCLK:
+ *value = metrics->AverageDclk0Frequency;
+ break;
+ case METRICS_AVERAGE_VCLK1:
+ *value = metrics->AverageVclk1Frequency;
+ break;
+ case METRICS_AVERAGE_DCLK1:
+ *value = metrics->AverageDclk1Frequency;
+ break;
+ case METRICS_AVERAGE_GFXACTIVITY:
+ *value = metrics->AverageGfxActivity;
+ break;
+ case METRICS_AVERAGE_MEMACTIVITY:
+ *value = metrics->AverageUclkActivity;
+ break;
+ case METRICS_AVERAGE_SOCKETPOWER:
+ *value = metrics->AverageSocketPower << 8;
+ break;
+ case METRICS_TEMPERATURE_EDGE:
+ *value = metrics->AvgTemperature[TEMP_EDGE] *
+ SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ break;
+ case METRICS_TEMPERATURE_HOTSPOT:
+ *value = metrics->AvgTemperature[TEMP_HOTSPOT] *
+ SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ break;
+ case METRICS_TEMPERATURE_MEM:
+ *value = metrics->AvgTemperature[TEMP_MEM] *
+ SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ break;
+ case METRICS_TEMPERATURE_VRGFX:
+ *value = metrics->AvgTemperature[TEMP_VR_GFX] *
+ SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ break;
+ case METRICS_TEMPERATURE_VRSOC:
+ *value = metrics->AvgTemperature[TEMP_VR_SOC] *
+ SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ break;
+ case METRICS_THROTTLER_STATUS:
+ *value = smu_v13_0_7_get_throttler_status(metrics);
+ break;
+ case METRICS_CURR_FANSPEED:
+ *value = metrics->AvgFanRpm;
+ break;
+ case METRICS_CURR_FANPWM:
+ *value = metrics->AvgFanPwm;
+ break;
+ case METRICS_VOLTAGE_VDDGFX:
+ *value = metrics->AvgVoltage[SVI_PLANE_GFX];
+ break;
+ case METRICS_PCIE_RATE:
+ *value = metrics->PcieRate;
+ break;
+ case METRICS_PCIE_WIDTH:
+ *value = metrics->PcieWidth;
+ break;
+ default:
+ *value = UINT_MAX;
+ break;
+ }
+
+ return ret;
+}
+
+static int smu_v13_0_7_read_sensor(struct smu_context *smu,
+ enum amd_pp_sensors sensor,
+ void *data,
+ uint32_t *size)
+{
+ struct smu_table_context *table_context = &smu->smu_table;
+ PPTable_t *smc_pptable = table_context->driver_pptable;
+ int ret = 0;
+
+ switch (sensor) {
+ case AMDGPU_PP_SENSOR_MAX_FAN_RPM:
+ *(uint16_t *)data = smc_pptable->SkuTable.FanMaximumRpm;
+ *size = 4;
+ break;
+ case AMDGPU_PP_SENSOR_MEM_LOAD:
+ ret = smu_v13_0_7_get_smu_metrics_data(smu,
+ METRICS_AVERAGE_MEMACTIVITY,
+ (uint32_t *)data);
+ *size = 4;
+ break;
+ case AMDGPU_PP_SENSOR_GPU_LOAD:
+ ret = smu_v13_0_7_get_smu_metrics_data(smu,
+ METRICS_AVERAGE_GFXACTIVITY,
+ (uint32_t *)data);
+ *size = 4;
+ break;
+ case AMDGPU_PP_SENSOR_GPU_POWER:
+ ret = smu_v13_0_7_get_smu_metrics_data(smu,
+ METRICS_AVERAGE_SOCKETPOWER,
+ (uint32_t *)data);
+ *size = 4;
+ break;
+ case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
+ ret = smu_v13_0_7_get_smu_metrics_data(smu,
+ METRICS_TEMPERATURE_HOTSPOT,
+ (uint32_t *)data);
+ *size = 4;
+ break;
+ case AMDGPU_PP_SENSOR_EDGE_TEMP:
+ ret = smu_v13_0_7_get_smu_metrics_data(smu,
+ METRICS_TEMPERATURE_EDGE,
+ (uint32_t *)data);
+ *size = 4;
+ break;
+ case AMDGPU_PP_SENSOR_MEM_TEMP:
+ ret = smu_v13_0_7_get_smu_metrics_data(smu,
+ METRICS_TEMPERATURE_MEM,
+ (uint32_t *)data);
+ *size = 4;
+ break;
+ case AMDGPU_PP_SENSOR_GFX_MCLK:
+ ret = smu_v13_0_7_get_smu_metrics_data(smu,
+ METRICS_AVERAGE_UCLK,
+ (uint32_t *)data);
+ *(uint32_t *)data *= 100;
+ *size = 4;
+ break;
+ case AMDGPU_PP_SENSOR_GFX_SCLK:
+ ret = smu_v13_0_7_get_smu_metrics_data(smu,
+ METRICS_AVERAGE_GFXCLK,
+ (uint32_t *)data);
+ *(uint32_t *)data *= 100;
+ *size = 4;
+ break;
+ case AMDGPU_PP_SENSOR_VDDGFX:
+ ret = smu_v13_0_7_get_smu_metrics_data(smu,
+ METRICS_VOLTAGE_VDDGFX,
+ (uint32_t *)data);
+ *size = 4;
+ break;
+ default:
+ ret = -EOPNOTSUPP;
+ break;
+ }
+
+ return ret;
+}
+
+static int smu_v13_0_7_get_current_clk_freq_by_table(struct smu_context *smu,
+ enum smu_clk_type clk_type,
+ uint32_t *value)
+{
+ MetricsMember_t member_type;
+ int clk_id = 0;
+
+ clk_id = smu_cmn_to_asic_specific_index(smu,
+ CMN2ASIC_MAPPING_CLK,
+ clk_type);
+ if (clk_id < 0)
+ return -EINVAL;
+
+ switch (clk_id) {
+ case PPCLK_GFXCLK:
+ member_type = METRICS_AVERAGE_GFXCLK;
+ break;
+ case PPCLK_UCLK:
+ member_type = METRICS_CURR_UCLK;
+ break;
+ case PPCLK_FCLK:
+ member_type = METRICS_CURR_FCLK;
+ break;
+ case PPCLK_SOCCLK:
+ member_type = METRICS_CURR_SOCCLK;
+ break;
+ case PPCLK_VCLK_0:
+ member_type = METRICS_CURR_VCLK;
+ break;
+ case PPCLK_DCLK_0:
+ member_type = METRICS_CURR_DCLK;
+ break;
+ case PPCLK_VCLK_1:
+ member_type = METRICS_CURR_VCLK1;
+ break;
+ case PPCLK_DCLK_1:
+ member_type = METRICS_CURR_DCLK1;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return smu_v13_0_7_get_smu_metrics_data(smu,
+ member_type,
+ value);
+}
+
+static int smu_v13_0_7_print_clk_levels(struct smu_context *smu,
+ enum smu_clk_type clk_type,
+ char *buf)
+{
+ struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
+ struct smu_13_0_dpm_context *dpm_context = smu_dpm->dpm_context;
+ struct smu_13_0_dpm_table *single_dpm_table;
+ struct smu_13_0_pcie_table *pcie_table;
+ uint32_t gen_speed, lane_width;
+ int i, curr_freq, size = 0;
+ int ret = 0;
+
+ smu_cmn_get_sysfs_buf(&buf, &size);
+
+ if (amdgpu_ras_intr_triggered()) {
+ size += sysfs_emit_at(buf, size, "unavailable\n");
+ return size;
+ }
+
+ switch (clk_type) {
+ case SMU_SCLK:
+ single_dpm_table = &(dpm_context->dpm_tables.gfx_table);
+ break;
+ case SMU_MCLK:
+ single_dpm_table = &(dpm_context->dpm_tables.uclk_table);
+ break;
+ case SMU_SOCCLK:
+ single_dpm_table = &(dpm_context->dpm_tables.soc_table);
+ break;
+ case SMU_FCLK:
+ single_dpm_table = &(dpm_context->dpm_tables.fclk_table);
+ break;
+ case SMU_VCLK:
+ case SMU_VCLK1:
+ single_dpm_table = &(dpm_context->dpm_tables.vclk_table);
+ break;
+ case SMU_DCLK:
+ case SMU_DCLK1:
+ single_dpm_table = &(dpm_context->dpm_tables.dclk_table);
+ break;
+ default:
+ break;
+ }
+
+ switch (clk_type) {
+ case SMU_SCLK:
+ case SMU_MCLK:
+ case SMU_SOCCLK:
+ case SMU_FCLK:
+ case SMU_VCLK:
+ case SMU_VCLK1:
+ case SMU_DCLK:
+ case SMU_DCLK1:
+ ret = smu_v13_0_7_get_current_clk_freq_by_table(smu, clk_type, &curr_freq);
+ if (ret) {
+ dev_err(smu->adev->dev, "Failed to get current clock freq!");
+ return ret;
+ }
+
+ if (single_dpm_table->is_fine_grained) {
+ /*
+ * For fine grained dpms, there are only two dpm levels:
+ * - level 0 -> min clock freq
+ * - level 1 -> max clock freq
+ * And the current clock frequency can be any value between them.
+ * So, if the current clock frequency is not at level 0 or level 1,
+ * we will fake it as three dpm levels:
+ * - level 0 -> min clock freq
+ * - level 1 -> current actual clock freq
+ * - level 2 -> max clock freq
+ */
+ if ((single_dpm_table->dpm_levels[0].value != curr_freq) &&
+ (single_dpm_table->dpm_levels[1].value != curr_freq)) {
+ size += sysfs_emit_at(buf, size, "0: %uMhz\n",
+ single_dpm_table->dpm_levels[0].value);
+ size += sysfs_emit_at(buf, size, "1: %uMhz *\n",
+ curr_freq);
+ size += sysfs_emit_at(buf, size, "2: %uMhz\n",
+ single_dpm_table->dpm_levels[1].value);
+ } else {
+ size += sysfs_emit_at(buf, size, "0: %uMhz %s\n",
+ single_dpm_table->dpm_levels[0].value,
+ single_dpm_table->dpm_levels[0].value == curr_freq ? "*" : "");
+ size += sysfs_emit_at(buf, size, "1: %uMhz %s\n",
+ single_dpm_table->dpm_levels[1].value,
+ single_dpm_table->dpm_levels[1].value == curr_freq ? "*" : "");
+ }
+ } else {
+ for (i = 0; i < single_dpm_table->count; i++)
+ size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n",
+ i, single_dpm_table->dpm_levels[i].value,
+ single_dpm_table->dpm_levels[i].value == curr_freq ? "*" : "");
+ }
+ break;
+ case SMU_PCIE:
+ ret = smu_v13_0_7_get_smu_metrics_data(smu,
+ METRICS_PCIE_RATE,
+ &gen_speed);
+ if (ret)
+ return ret;
+
+ ret = smu_v13_0_7_get_smu_metrics_data(smu,
+ METRICS_PCIE_WIDTH,
+ &lane_width);
+ if (ret)
+ return ret;
+
+ pcie_table = &(dpm_context->dpm_tables.pcie_table);
+ for (i = 0; i < pcie_table->num_of_link_levels; i++)
+ size += sysfs_emit_at(buf, size, "%d: %s %s %dMhz %s\n", i,
+ (pcie_table->pcie_gen[i] == 0) ? "2.5GT/s," :
+ (pcie_table->pcie_gen[i] == 1) ? "5.0GT/s," :
+ (pcie_table->pcie_gen[i] == 2) ? "8.0GT/s," :
+ (pcie_table->pcie_gen[i] == 3) ? "16.0GT/s," : "",
+ (pcie_table->pcie_lane[i] == 1) ? "x1" :
+ (pcie_table->pcie_lane[i] == 2) ? "x2" :
+ (pcie_table->pcie_lane[i] == 3) ? "x4" :
+ (pcie_table->pcie_lane[i] == 4) ? "x8" :
+ (pcie_table->pcie_lane[i] == 5) ? "x12" :
+ (pcie_table->pcie_lane[i] == 6) ? "x16" : "",
+ pcie_table->clk_freq[i],
+ (gen_speed == pcie_table->pcie_gen[i]) &&
+ (lane_width == pcie_table->pcie_lane[i]) ?
+ "*" : "");
+ break;
+
+ default:
+ break;
+ }
+
+ return size;
+}
+
+static int smu_v13_0_7_force_clk_levels(struct smu_context *smu,
+ enum smu_clk_type clk_type,
+ uint32_t mask)
+{
+ struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
+ struct smu_13_0_dpm_context *dpm_context = smu_dpm->dpm_context;
+ struct smu_13_0_dpm_table *single_dpm_table;
+ uint32_t soft_min_level, soft_max_level;
+ uint32_t min_freq, max_freq;
+ int ret = 0;
+
+ soft_min_level = mask ? (ffs(mask) - 1) : 0;
+ soft_max_level = mask ? (fls(mask) - 1) : 0;
+
+ switch (clk_type) {
+ case SMU_GFXCLK:
+ case SMU_SCLK:
+ single_dpm_table = &(dpm_context->dpm_tables.gfx_table);
+ break;
+ case SMU_MCLK:
+ case SMU_UCLK:
+ single_dpm_table = &(dpm_context->dpm_tables.uclk_table);
+ break;
+ case SMU_SOCCLK:
+ single_dpm_table = &(dpm_context->dpm_tables.soc_table);
+ break;
+ case SMU_FCLK:
+ single_dpm_table = &(dpm_context->dpm_tables.fclk_table);
+ break;
+ case SMU_VCLK:
+ case SMU_VCLK1:
+ single_dpm_table = &(dpm_context->dpm_tables.vclk_table);
+ break;
+ case SMU_DCLK:
+ case SMU_DCLK1:
+ single_dpm_table = &(dpm_context->dpm_tables.dclk_table);
+ break;
+ default:
+ break;
+ }
+
+ switch (clk_type) {
+ case SMU_GFXCLK:
+ case SMU_SCLK:
+ case SMU_MCLK:
+ case SMU_UCLK:
+ case SMU_SOCCLK:
+ case SMU_FCLK:
+ case SMU_VCLK:
+ case SMU_VCLK1:
+ case SMU_DCLK:
+ case SMU_DCLK1:
+ if (single_dpm_table->is_fine_grained) {
+ /* There is only 2 levels for fine grained DPM */
+ soft_max_level = (soft_max_level >= 1 ? 1 : 0);
+ soft_min_level = (soft_min_level >= 1 ? 1 : 0);
+ } else {
+ if ((soft_max_level >= single_dpm_table->count) ||
+ (soft_min_level >= single_dpm_table->count))
+ return -EINVAL;
+ }
+
+ min_freq = single_dpm_table->dpm_levels[soft_min_level].value;
+ max_freq = single_dpm_table->dpm_levels[soft_max_level].value;
+
+ ret = smu_v13_0_set_soft_freq_limited_range(smu,
+ clk_type,
+ min_freq,
+ max_freq);
+ break;
+ case SMU_DCEFCLK:
+ case SMU_PCIE:
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+static int smu_v13_0_7_update_pcie_parameters(struct smu_context *smu,
+ uint32_t pcie_gen_cap,
+ uint32_t pcie_width_cap)
+{
+ struct smu_13_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context;
+ struct smu_13_0_pcie_table *pcie_table =
+ &dpm_context->dpm_tables.pcie_table;
+ uint32_t smu_pcie_arg;
+ int ret, i;
+
+ for (i = 0; i < pcie_table->num_of_link_levels; i++) {
+ if (pcie_table->pcie_gen[i] > pcie_gen_cap)
+ pcie_table->pcie_gen[i] = pcie_gen_cap;
+ if (pcie_table->pcie_lane[i] > pcie_width_cap)
+ pcie_table->pcie_lane[i] = pcie_width_cap;
+
+ smu_pcie_arg = i << 16;
+ smu_pcie_arg |= pcie_table->pcie_gen[i] << 8;
+ smu_pcie_arg |= pcie_table->pcie_lane[i];
+
+ ret = smu_cmn_send_smc_msg_with_param(smu,
+ SMU_MSG_OverridePcieParameters,
+ smu_pcie_arg,
+ NULL);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct smu_temperature_range smu13_thermal_policy[] =
+{
+ {-273150, 99000, 99000, -273150, 99000, 99000, -273150, 99000, 99000},
+ { 120000, 120000, 120000, 120000, 120000, 120000, 120000, 120000, 120000},
+};
+
+static int smu_v13_0_7_get_thermal_temperature_range(struct smu_context *smu,
+ struct smu_temperature_range *range)
+{
+ struct smu_table_context *table_context = &smu->smu_table;
+ struct smu_13_0_7_powerplay_table *powerplay_table =
+ table_context->power_play_table;
+ PPTable_t *pptable = smu->smu_table.driver_pptable;
+
+ if (!range)
+ return -EINVAL;
+
+ memcpy(range, &smu13_thermal_policy[0], sizeof(struct smu_temperature_range));
+
+ range->max = pptable->SkuTable.TemperatureLimit[TEMP_EDGE] *
+ SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ range->edge_emergency_max = (pptable->SkuTable.TemperatureLimit[TEMP_EDGE] + CTF_OFFSET_EDGE) *
+ SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ range->hotspot_crit_max = pptable->SkuTable.TemperatureLimit[TEMP_HOTSPOT] *
+ SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ range->hotspot_emergency_max = (pptable->SkuTable.TemperatureLimit[TEMP_HOTSPOT] + CTF_OFFSET_HOTSPOT) *
+ SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ range->mem_crit_max = pptable->SkuTable.TemperatureLimit[TEMP_MEM] *
+ SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ range->mem_emergency_max = (pptable->SkuTable.TemperatureLimit[TEMP_MEM] + CTF_OFFSET_MEM)*
+ SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ range->software_shutdown_temp = powerplay_table->software_shutdown_temp;
+
+ return 0;
+}
+
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+static ssize_t smu_v13_0_7_get_gpu_metrics(struct smu_context *smu,
+ void **table)
+{
+ struct smu_table_context *smu_table = &smu->smu_table;
+ struct gpu_metrics_v1_3 *gpu_metrics =
+ (struct gpu_metrics_v1_3 *)smu_table->gpu_metrics_table;
+ SmuMetricsExternal_t metrics_ext;
+ SmuMetrics_t *metrics = &metrics_ext.SmuMetrics;
+ int ret = 0;
+
+ ret = smu_cmn_get_metrics_table(smu,
+ &metrics_ext,
+ true);
+ if (ret)
+ return ret;
+
+ smu_cmn_init_soft_gpu_metrics(gpu_metrics, 1, 3);
+
+ gpu_metrics->temperature_edge = metrics->AvgTemperature[TEMP_EDGE];
+ gpu_metrics->temperature_hotspot = metrics->AvgTemperature[TEMP_HOTSPOT];
+ gpu_metrics->temperature_mem = metrics->AvgTemperature[TEMP_MEM];
+ gpu_metrics->temperature_vrgfx = metrics->AvgTemperature[TEMP_VR_GFX];
+ gpu_metrics->temperature_vrsoc = metrics->AvgTemperature[TEMP_VR_SOC];
+ gpu_metrics->temperature_vrmem = MAX(metrics->AvgTemperature[TEMP_VR_MEM0],
+ metrics->AvgTemperature[TEMP_VR_MEM1]);
+
+ gpu_metrics->average_gfx_activity = metrics->AverageGfxActivity;
+ gpu_metrics->average_umc_activity = metrics->AverageUclkActivity;
+ gpu_metrics->average_mm_activity = MAX(metrics->Vcn0ActivityPercentage,
+ metrics->Vcn1ActivityPercentage);
+
+ gpu_metrics->average_socket_power = metrics->AverageSocketPower;
+ gpu_metrics->energy_accumulator = metrics->EnergyAccumulator;
+
+ if (metrics->AverageGfxActivity <= SMU_13_0_7_BUSY_THRESHOLD)
+ gpu_metrics->average_gfxclk_frequency = metrics->AverageGfxclkFrequencyPostDs;
+ else
+ gpu_metrics->average_gfxclk_frequency = metrics->AverageGfxclkFrequencyPreDs;
+
+ if (metrics->AverageUclkActivity <= SMU_13_0_7_BUSY_THRESHOLD)
+ gpu_metrics->average_uclk_frequency = metrics->AverageMemclkFrequencyPostDs;
+ else
+ gpu_metrics->average_uclk_frequency = metrics->AverageMemclkFrequencyPreDs;
+
+ gpu_metrics->average_vclk0_frequency = metrics->AverageVclk0Frequency;
+ gpu_metrics->average_dclk0_frequency = metrics->AverageDclk0Frequency;
+ gpu_metrics->average_vclk1_frequency = metrics->AverageVclk1Frequency;
+ gpu_metrics->average_dclk1_frequency = metrics->AverageDclk1Frequency;
+
+ gpu_metrics->current_gfxclk = metrics->CurrClock[PPCLK_GFXCLK];
+ gpu_metrics->current_vclk0 = metrics->CurrClock[PPCLK_VCLK_0];
+ gpu_metrics->current_dclk0 = metrics->CurrClock[PPCLK_DCLK_0];
+ gpu_metrics->current_vclk1 = metrics->CurrClock[PPCLK_VCLK_1];
+ gpu_metrics->current_dclk1 = metrics->CurrClock[PPCLK_DCLK_1];
+
+ gpu_metrics->throttle_status =
+ smu_v13_0_7_get_throttler_status(metrics);
+ gpu_metrics->indep_throttle_status =
+ smu_cmn_get_indep_throttler_status(gpu_metrics->throttle_status,
+ smu_v13_0_7_throttler_map);
+
+ gpu_metrics->current_fan_speed = metrics->AvgFanRpm;
+
+ gpu_metrics->pcie_link_width = metrics->PcieWidth;
+ gpu_metrics->pcie_link_speed = metrics->PcieRate;
+
+ gpu_metrics->system_clock_counter = ktime_get_boottime_ns();
+
+ gpu_metrics->voltage_gfx = metrics->AvgVoltage[SVI_PLANE_GFX];
+ gpu_metrics->voltage_soc = metrics->AvgVoltage[SVI_PLANE_SOC];
+ gpu_metrics->voltage_mem = metrics->AvgVoltage[SVI_PLANE_VMEMP];
+
+ *table = (void *)gpu_metrics;
+
+ return sizeof(struct gpu_metrics_v1_3);
+}
+
+static int smu_v13_0_7_populate_umd_state_clk(struct smu_context *smu)
+{
+ struct smu_13_0_dpm_context *dpm_context =
+ smu->smu_dpm.dpm_context;
+ struct smu_13_0_dpm_table *gfx_table =
+ &dpm_context->dpm_tables.gfx_table;
+ struct smu_13_0_dpm_table *mem_table =
+ &dpm_context->dpm_tables.uclk_table;
+ struct smu_13_0_dpm_table *soc_table =
+ &dpm_context->dpm_tables.soc_table;
+ struct smu_13_0_dpm_table *vclk_table =
+ &dpm_context->dpm_tables.vclk_table;
+ struct smu_13_0_dpm_table *dclk_table =
+ &dpm_context->dpm_tables.dclk_table;
+ struct smu_13_0_dpm_table *fclk_table =
+ &dpm_context->dpm_tables.fclk_table;
+ struct smu_umd_pstate_table *pstate_table =
+ &smu->pstate_table;
+
+ pstate_table->gfxclk_pstate.min = gfx_table->min;
+ pstate_table->gfxclk_pstate.peak = gfx_table->max;
+
+ pstate_table->uclk_pstate.min = mem_table->min;
+ pstate_table->uclk_pstate.peak = mem_table->max;
+
+ pstate_table->socclk_pstate.min = soc_table->min;
+ pstate_table->socclk_pstate.peak = soc_table->max;
+
+ pstate_table->vclk_pstate.min = vclk_table->min;
+ pstate_table->vclk_pstate.peak = vclk_table->max;
+
+ pstate_table->dclk_pstate.min = dclk_table->min;
+ pstate_table->dclk_pstate.peak = dclk_table->max;
+
+ pstate_table->fclk_pstate.min = fclk_table->min;
+ pstate_table->fclk_pstate.peak = fclk_table->max;
+
+ /*
+ * For now, just use the mininum clock frequency.
+ * TODO: update them when the real pstate settings available
+ */
+ pstate_table->gfxclk_pstate.standard = gfx_table->min;
+ pstate_table->uclk_pstate.standard = mem_table->min;
+ pstate_table->socclk_pstate.standard = soc_table->min;
+ pstate_table->vclk_pstate.standard = vclk_table->min;
+ pstate_table->dclk_pstate.standard = dclk_table->min;
+ pstate_table->fclk_pstate.standard = fclk_table->min;
+
+ return 0;
+}
+
+static int smu_v13_0_7_get_fan_speed_pwm(struct smu_context *smu,
+ uint32_t *speed)
+{
+ if (!speed)
+ return -EINVAL;
+
+ return smu_v13_0_7_get_smu_metrics_data(smu,
+ METRICS_CURR_FANPWM,
+ speed);
+}
+
+static int smu_v13_0_7_get_fan_speed_rpm(struct smu_context *smu,
+ uint32_t *speed)
+{
+ if (!speed)
+ return -EINVAL;
+
+ return smu_v13_0_7_get_smu_metrics_data(smu,
+ METRICS_CURR_FANSPEED,
+ speed);
+}
+
+static int smu_v13_0_7_enable_mgpu_fan_boost(struct smu_context *smu)
+{
+ struct smu_table_context *table_context = &smu->smu_table;
+ PPTable_t *pptable = table_context->driver_pptable;
+ SkuTable_t *skutable = &pptable->SkuTable;
+
+ /*
+ * Skip the MGpuFanBoost setting for those ASICs
+ * which do not support it
+ */
+ if (skutable->MGpuAcousticLimitRpmThreshold == 0)
+ return 0;
+
+ return smu_cmn_send_smc_msg_with_param(smu,
+ SMU_MSG_SetMGpuFanBoostLimitRpm,
+ 0,
+ NULL);
+}
+
+static int smu_v13_0_7_get_power_limit(struct smu_context *smu,
+ uint32_t *current_power_limit,
+ uint32_t *default_power_limit,
+ uint32_t *max_power_limit)
+{
+ struct smu_table_context *table_context = &smu->smu_table;
+ struct smu_13_0_7_powerplay_table *powerplay_table =
+ (struct smu_13_0_7_powerplay_table *)table_context->power_play_table;
+ PPTable_t *pptable = table_context->driver_pptable;
+ SkuTable_t *skutable = &pptable->SkuTable;
+ uint32_t power_limit, od_percent;
+
+ if (smu_v13_0_get_current_power_limit(smu, &power_limit))
+ power_limit = smu->adev->pm.ac_power ?
+ skutable->SocketPowerLimitAc[PPT_THROTTLER_PPT0] :
+ skutable->SocketPowerLimitDc[PPT_THROTTLER_PPT0];
+
+ if (current_power_limit)
+ *current_power_limit = power_limit;
+ if (default_power_limit)
+ *default_power_limit = power_limit;
+
+ if (max_power_limit) {
+ if (smu->od_enabled) {
+ od_percent = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_13_0_7_ODSETTING_POWERPERCENTAGE]);
+
+ dev_dbg(smu->adev->dev, "ODSETTING_POWERPERCENTAGE: %d (default: %d)\n", od_percent, power_limit);
+
+ power_limit *= (100 + od_percent);
+ power_limit /= 100;
+ }
+ *max_power_limit = power_limit;
+ }
+
+ return 0;
+}
+
+static int smu_v13_0_7_get_power_profile_mode(struct smu_context *smu, char *buf)
+{
+ DpmActivityMonitorCoeffIntExternal_t activity_monitor_external[PP_SMC_POWER_PROFILE_COUNT];
+ uint32_t i, j, size = 0;
+ int16_t workload_type = 0;
+ int result = 0;
+
+ if (!buf)
+ return -EINVAL;
+
+ size += sysfs_emit_at(buf, size, " ");
+ for (i = 0; i <= PP_SMC_POWER_PROFILE_WINDOW3D; i++)
+ size += sysfs_emit_at(buf, size, "%-14s%s", amdgpu_pp_profile_name[i],
+ (i == smu->power_profile_mode) ? "* " : " ");
+
+ size += sysfs_emit_at(buf, size, "\n");
+
+ for (i = 0; i <= PP_SMC_POWER_PROFILE_WINDOW3D; i++) {
+ /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
+ workload_type = smu_cmn_to_asic_specific_index(smu,
+ CMN2ASIC_MAPPING_WORKLOAD,
+ i);
+ if (workload_type < 0)
+ return -EINVAL;
+
+ result = smu_cmn_update_table(smu,
+ SMU_TABLE_ACTIVITY_MONITOR_COEFF, workload_type,
+ (void *)(&activity_monitor_external[i]), false);
+ if (result) {
+ dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
+ return result;
+ }
+ }
+
+#define PRINT_DPM_MONITOR(field) \
+do { \
+ size += sysfs_emit_at(buf, size, "%-30s", #field); \
+ for (j = 0; j <= PP_SMC_POWER_PROFILE_WINDOW3D; j++) \
+ size += sysfs_emit_at(buf, size, "%-16d", activity_monitor_external[j].DpmActivityMonitorCoeffInt.field); \
+ size += sysfs_emit_at(buf, size, "\n"); \
+} while (0)
+
+ PRINT_DPM_MONITOR(Gfx_ActiveHystLimit);
+ PRINT_DPM_MONITOR(Gfx_IdleHystLimit);
+ PRINT_DPM_MONITOR(Gfx_FPS);
+ PRINT_DPM_MONITOR(Gfx_MinActiveFreqType);
+ PRINT_DPM_MONITOR(Gfx_BoosterFreqType);
+ PRINT_DPM_MONITOR(Gfx_MinActiveFreq);
+ PRINT_DPM_MONITOR(Gfx_BoosterFreq);
+ PRINT_DPM_MONITOR(Fclk_ActiveHystLimit);
+ PRINT_DPM_MONITOR(Fclk_IdleHystLimit);
+ PRINT_DPM_MONITOR(Fclk_FPS);
+ PRINT_DPM_MONITOR(Fclk_MinActiveFreqType);
+ PRINT_DPM_MONITOR(Fclk_BoosterFreqType);
+ PRINT_DPM_MONITOR(Fclk_MinActiveFreq);
+ PRINT_DPM_MONITOR(Fclk_BoosterFreq);
+#undef PRINT_DPM_MONITOR
+
+ return size;
+}
+
+static int smu_v13_0_7_set_power_profile_mode(struct smu_context *smu, long *input, uint32_t size)
+{
+
+ DpmActivityMonitorCoeffIntExternal_t activity_monitor_external;
+ DpmActivityMonitorCoeffInt_t *activity_monitor =
+ &(activity_monitor_external.DpmActivityMonitorCoeffInt);
+ int workload_type, ret = 0;
+
+ smu->power_profile_mode = input[size];
+
+ if (smu->power_profile_mode > PP_SMC_POWER_PROFILE_WINDOW3D) {
+ dev_err(smu->adev->dev, "Invalid power profile mode %d\n", smu->power_profile_mode);
+ return -EINVAL;
+ }
+
+ if (smu->power_profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) {
+
+ ret = smu_cmn_update_table(smu,
+ SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
+ (void *)(&activity_monitor_external), false);
+ if (ret) {
+ dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
+ return ret;
+ }
+
+ switch (input[0]) {
+ case 0: /* Gfxclk */
+ activity_monitor->Gfx_ActiveHystLimit = input[1];
+ activity_monitor->Gfx_IdleHystLimit = input[2];
+ activity_monitor->Gfx_FPS = input[3];
+ activity_monitor->Gfx_MinActiveFreqType = input[4];
+ activity_monitor->Gfx_BoosterFreqType = input[5];
+ activity_monitor->Gfx_MinActiveFreq = input[6];
+ activity_monitor->Gfx_BoosterFreq = input[7];
+ break;
+ case 1: /* Fclk */
+ activity_monitor->Fclk_ActiveHystLimit = input[1];
+ activity_monitor->Fclk_IdleHystLimit = input[2];
+ activity_monitor->Fclk_FPS = input[3];
+ activity_monitor->Fclk_MinActiveFreqType = input[4];
+ activity_monitor->Fclk_BoosterFreqType = input[5];
+ activity_monitor->Fclk_MinActiveFreq = input[6];
+ activity_monitor->Fclk_BoosterFreq = input[7];
+ break;
+ }
+
+ ret = smu_cmn_update_table(smu,
+ SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
+ (void *)(&activity_monitor_external), true);
+ if (ret) {
+ dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__);
+ return ret;
+ }
+ }
+
+ /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
+ workload_type = smu_cmn_to_asic_specific_index(smu,
+ CMN2ASIC_MAPPING_WORKLOAD,
+ smu->power_profile_mode);
+ if (workload_type < 0)
+ return -EINVAL;
+ smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,
+ 1 << workload_type, NULL);
+
+ return ret;
+}
+
+static const struct pptable_funcs smu_v13_0_7_ppt_funcs = {
+ .get_allowed_feature_mask = smu_v13_0_7_get_allowed_feature_mask,
+ .set_default_dpm_table = smu_v13_0_7_set_default_dpm_table,
+ .is_dpm_running = smu_v13_0_7_is_dpm_running,
+ .dump_pptable = smu_v13_0_7_dump_pptable,
+ .init_microcode = smu_v13_0_init_microcode,
+ .load_microcode = smu_v13_0_load_microcode,
+ .init_smc_tables = smu_v13_0_7_init_smc_tables,
+ .init_power = smu_v13_0_init_power,
+ .check_fw_status = smu_v13_0_7_check_fw_status,
+ .setup_pptable = smu_v13_0_7_setup_pptable,
+ .check_fw_version = smu_v13_0_check_fw_version,
+ .write_pptable = smu_cmn_write_pptable,
+ .set_driver_table_location = smu_v13_0_set_driver_table_location,
+ .system_features_control = smu_v13_0_system_features_control,
+ .set_allowed_mask = smu_v13_0_set_allowed_mask,
+ .get_enabled_mask = smu_cmn_get_enabled_mask,
+ .dpm_set_vcn_enable = smu_v13_0_set_vcn_enable,
+ .dpm_set_jpeg_enable = smu_v13_0_set_jpeg_enable,
+ .init_pptable_microcode = smu_v13_0_init_pptable_microcode,
+ .populate_umd_state_clk = smu_v13_0_7_populate_umd_state_clk,
+ .get_dpm_ultimate_freq = smu_v13_0_get_dpm_ultimate_freq,
+ .get_vbios_bootup_values = smu_v13_0_get_vbios_bootup_values,
+ .read_sensor = smu_v13_0_7_read_sensor,
+ .feature_is_enabled = smu_cmn_feature_is_enabled,
+ .print_clk_levels = smu_v13_0_7_print_clk_levels,
+ .force_clk_levels = smu_v13_0_7_force_clk_levels,
+ .update_pcie_parameters = smu_v13_0_7_update_pcie_parameters,
+ .get_thermal_temperature_range = smu_v13_0_7_get_thermal_temperature_range,
+ .register_irq_handler = smu_v13_0_register_irq_handler,
+ .enable_thermal_alert = smu_v13_0_enable_thermal_alert,
+ .disable_thermal_alert = smu_v13_0_disable_thermal_alert,
+ .notify_memory_pool_location = smu_v13_0_notify_memory_pool_location,
+ .get_gpu_metrics = smu_v13_0_7_get_gpu_metrics,
+ .set_soft_freq_limited_range = smu_v13_0_set_soft_freq_limited_range,
+ .set_performance_level = smu_v13_0_set_performance_level,
+ .gfx_off_control = smu_v13_0_gfx_off_control,
+ .get_fan_speed_pwm = smu_v13_0_7_get_fan_speed_pwm,
+ .get_fan_speed_rpm = smu_v13_0_7_get_fan_speed_rpm,
+ .set_fan_speed_pwm = smu_v13_0_set_fan_speed_pwm,
+ .set_fan_speed_rpm = smu_v13_0_set_fan_speed_rpm,
+ .get_fan_control_mode = smu_v13_0_get_fan_control_mode,
+ .set_fan_control_mode = smu_v13_0_set_fan_control_mode,
+ .enable_mgpu_fan_boost = smu_v13_0_7_enable_mgpu_fan_boost,
+ .get_power_limit = smu_v13_0_7_get_power_limit,
+ .set_power_limit = smu_v13_0_set_power_limit,
+ .get_power_profile_mode = smu_v13_0_7_get_power_profile_mode,
+ .set_power_profile_mode = smu_v13_0_7_set_power_profile_mode,
+ .set_tool_table_location = smu_v13_0_set_tool_table_location,
+ .get_pp_feature_mask = smu_cmn_get_pp_feature_mask,
+ .set_pp_feature_mask = smu_cmn_set_pp_feature_mask,
+};
+
+void smu_v13_0_7_set_ppt_funcs(struct smu_context *smu)
+{
+ smu->ppt_funcs = &smu_v13_0_7_ppt_funcs;
+ smu->message_map = smu_v13_0_7_message_map;
+ smu->clock_map = smu_v13_0_7_clk_map;
+ smu->feature_map = smu_v13_0_7_feature_mask_map;
+ smu->table_map = smu_v13_0_7_table_map;
+ smu->pwr_src_map = smu_v13_0_7_pwr_src_map;
+ smu->workload_map = smu_v13_0_7_workload_map;
+}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.h b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.h
new file mode 100644
index 000000000000..a4763cfedc4f
--- /dev/null
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2021 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+#ifndef __SMU_V13_0_7_PPT_H__
+#define __SMU_V13_0_7_PPT_H__
+
+extern void smu_v13_0_7_set_ppt_funcs(struct smu_context *smu);
+
+#endif
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c
index e2d099409123..87257b1b028f 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c
@@ -276,6 +276,42 @@ static int yellow_carp_mode2_reset(struct smu_context *smu)
return yellow_carp_mode_reset(smu, SMU_RESET_MODE_2);
}
+
+static void yellow_carp_get_ss_power_percent(SmuMetrics_t *metrics,
+ uint32_t *apu_percent, uint32_t *dgpu_percent)
+{
+ uint32_t apu_boost = 0;
+ uint32_t dgpu_boost = 0;
+ uint16_t apu_limit = 0;
+ uint16_t dgpu_limit = 0;
+ uint16_t apu_power = 0;
+ uint16_t dgpu_power = 0;
+
+ /* APU and dGPU power values are reported in milli Watts
+ * and STAPM power limits are in Watts */
+ apu_power = metrics->ApuPower/1000;
+ apu_limit = metrics->StapmOpnLimit;
+ if (apu_power > apu_limit && apu_limit != 0)
+ apu_boost = ((apu_power - apu_limit) * 100) / apu_limit;
+ apu_boost = (apu_boost > 100) ? 100 : apu_boost;
+
+ dgpu_power = metrics->dGpuPower/1000;
+ if (metrics->StapmCurrentLimit > metrics->StapmOpnLimit)
+ dgpu_limit = metrics->StapmCurrentLimit - metrics->StapmOpnLimit;
+ if (dgpu_power > dgpu_limit && dgpu_limit != 0)
+ dgpu_boost = ((dgpu_power - dgpu_limit) * 100) / dgpu_limit;
+ dgpu_boost = (dgpu_boost > 100) ? 100 : dgpu_boost;
+
+ if (dgpu_boost >= apu_boost)
+ apu_boost = 0;
+ else
+ dgpu_boost = 0;
+
+ *apu_percent = apu_boost;
+ *dgpu_percent = dgpu_boost;
+
+}
+
static int yellow_carp_get_smu_metrics_data(struct smu_context *smu,
MetricsMember_t member,
uint32_t *value)
@@ -284,6 +320,8 @@ static int yellow_carp_get_smu_metrics_data(struct smu_context *smu,
SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table;
int ret = 0;
+ uint32_t apu_percent = 0;
+ uint32_t dgpu_percent = 0;
ret = smu_cmn_get_metrics_table(smu, NULL, false);
if (ret)
@@ -332,26 +370,18 @@ static int yellow_carp_get_smu_metrics_data(struct smu_context *smu,
*value = metrics->Voltage[1];
break;
case METRICS_SS_APU_SHARE:
- /* return the percentage of APU power with respect to APU's power limit.
- * percentage is reported, this isn't boost value. Smartshift power
- * boost/shift is only when the percentage is more than 100.
+ /* return the percentage of APU power boost
+ * with respect to APU's power limit.
*/
- if (metrics->StapmOpnLimit > 0)
- *value = (metrics->ApuPower * 100) / metrics->StapmOpnLimit;
- else
- *value = 0;
+ yellow_carp_get_ss_power_percent(metrics, &apu_percent, &dgpu_percent);
+ *value = apu_percent;
break;
case METRICS_SS_DGPU_SHARE:
- /* return the percentage of dGPU power with respect to dGPU's power limit.
- * percentage is reported, this isn't boost value. Smartshift power
- * boost/shift is only when the percentage is more than 100.
+ /* return the percentage of dGPU power boost
+ * with respect to dGPU's power limit.
*/
- if ((metrics->dGpuPower > 0) &&
- (metrics->StapmCurrentLimit > metrics->StapmOpnLimit))
- *value = (metrics->dGpuPower * 100) /
- (metrics->StapmCurrentLimit - metrics->StapmOpnLimit);
- else
- *value = 0;
+ yellow_carp_get_ss_power_percent(metrics, &apu_percent, &dgpu_percent);
+ *value = dgpu_percent;
break;
default:
*value = UINT_MAX;
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
index f12319883a80..5de7da75d14a 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
@@ -497,7 +497,7 @@ int smu_cmn_to_asic_specific_index(struct smu_context *smu,
return mapping.map_to;
case CMN2ASIC_MAPPING_WORKLOAD:
- if (index > PP_SMC_POWER_PROFILE_CUSTOM ||
+ if (index > PP_SMC_POWER_PROFILE_WINDOW3D ||
!smu->workload_map)
return -EINVAL;
@@ -581,6 +581,17 @@ bool smu_cmn_clk_dpm_is_enabled(struct smu_context *smu,
case SMU_SOCCLK:
feature_id = SMU_FEATURE_DPM_SOCCLK_BIT;
break;
+ case SMU_VCLK:
+ case SMU_VCLK1:
+ feature_id = SMU_FEATURE_DPM_VCLK_BIT;
+ break;
+ case SMU_DCLK:
+ case SMU_DCLK1:
+ feature_id = SMU_FEATURE_DPM_DCLK_BIT;
+ break;
+ case SMU_FCLK:
+ feature_id = SMU_FEATURE_DPM_FCLK_BIT;
+ break;
default:
return true;
}
@@ -971,6 +982,17 @@ int smu_cmn_get_metrics_table(struct smu_context *smu,
return 0;
}
+int smu_cmn_get_combo_pptable(struct smu_context *smu)
+{
+ void *pptable = smu->smu_table.combo_pptable;
+
+ return smu_cmn_update_table(smu,
+ SMU_TABLE_COMBO_PPTABLE,
+ 0,
+ pptable,
+ false);
+}
+
void smu_cmn_init_soft_gpu_metrics(void *table, uint8_t frev, uint8_t crev)
{
struct metrics_table_header *header = (struct metrics_table_header *)table;
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h
index a4c593ed8b03..1526ce09c399 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h
@@ -99,6 +99,8 @@ int smu_cmn_get_metrics_table(struct smu_context *smu,
void *metrics_table,
bool bypass_cache);
+int smu_cmn_get_combo_pptable(struct smu_context *smu);
+
void smu_cmn_init_soft_gpu_metrics(void *table, uint8_t frev, uint8_t crev);
int smu_cmn_set_mp1_state(struct smu_context *smu,
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h b/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h
index 5f21ead860f9..7469bbfce1fb 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h
@@ -93,6 +93,7 @@
#define smu_set_fine_grain_gfx_freq_parameters(smu) smu_ppt_funcs(set_fine_grain_gfx_freq_parameters, 0, smu)
#define smu_get_default_config_table_settings(smu, config_table) smu_ppt_funcs(get_default_config_table_settings, -EOPNOTSUPP, smu, config_table)
#define smu_set_config_table(smu, config_table) smu_ppt_funcs(set_config_table, -EOPNOTSUPP, smu, config_table)
+#define smu_init_pptable_microcode(smu) smu_ppt_funcs(init_pptable_microcode, 0, smu)
#endif
#endif