aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorEvan Quan <evan.quan@amd.com>2019-01-14 02:44:44 -0500
committerAlex Deucher <alexander.deucher@amd.com>2019-01-25 16:15:34 -0500
commit828e37efe802ba8c868922af23099638fde5b7b4 (patch)
tree6860d47f01d20d92cfe804fe970f0c8b61422177 /drivers/gpu/drm
parentd7337ca2640cde21ff178bd78f01d94cd5ea2e08 (diff)
drm/amd/powerplay: support retrieving and adjusting fclock power levels V2
User can use "pp_dpm_fclk" to retrieve and adjust fclock power levels. V2: expose this interface for Vega20 and later ASICs only Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c53
-rw-r--r--drivers/gpu/drm/amd/include/kgd_pp_interface.h1
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c64
3 files changed, 116 insertions, 2 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
index 4bdb1d082bea..23eb6f61da13 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
@@ -680,13 +680,14 @@ static ssize_t amdgpu_get_ppfeature_status(struct device *dev,
680} 680}
681 681
682/** 682/**
683 * DOC: pp_dpm_sclk pp_dpm_mclk pp_dpm_socclk pp_dpm_pcie 683 * DOC: pp_dpm_sclk pp_dpm_mclk pp_dpm_socclk pp_dpm_fclk pp_dpm_pcie
684 * 684 *
685 * The amdgpu driver provides a sysfs API for adjusting what power levels 685 * The amdgpu driver provides a sysfs API for adjusting what power levels
686 * are enabled for a given power state. The files pp_dpm_sclk, pp_dpm_mclk, 686 * are enabled for a given power state. The files pp_dpm_sclk, pp_dpm_mclk,
687 * pp_dpm_socclk and pp_dpm_pcie are used for this. 687 * pp_dpm_socclk, pp_dpm_fclk and pp_dpm_pcie are used for this.
688 * 688 *
689 * pp_dpm_socclk interface is only available for Vega10 and later ASICs. 689 * pp_dpm_socclk interface is only available for Vega10 and later ASICs.
690 * pp_dpm_fclk interface is only available for Vega20 and later ASICs.
690 * 691 *
691 * Reading back the files will show you the available power levels within 692 * Reading back the files will show you the available power levels within
692 * the power state and the clock information for those levels. 693 * the power state and the clock information for those levels.
@@ -842,6 +843,42 @@ static ssize_t amdgpu_set_pp_dpm_socclk(struct device *dev,
842 return count; 843 return count;
843} 844}
844 845
846static ssize_t amdgpu_get_pp_dpm_fclk(struct device *dev,
847 struct device_attribute *attr,
848 char *buf)
849{
850 struct drm_device *ddev = dev_get_drvdata(dev);
851 struct amdgpu_device *adev = ddev->dev_private;
852
853 if (adev->powerplay.pp_funcs->print_clock_levels)
854 return amdgpu_dpm_print_clock_levels(adev, PP_FCLK, buf);
855 else
856 return snprintf(buf, PAGE_SIZE, "\n");
857}
858
859static ssize_t amdgpu_set_pp_dpm_fclk(struct device *dev,
860 struct device_attribute *attr,
861 const char *buf,
862 size_t count)
863{
864 struct drm_device *ddev = dev_get_drvdata(dev);
865 struct amdgpu_device *adev = ddev->dev_private;
866 int ret;
867 uint32_t mask = 0;
868
869 ret = amdgpu_read_mask(buf, count, &mask);
870 if (ret)
871 return ret;
872
873 if (adev->powerplay.pp_funcs->force_clock_level)
874 ret = amdgpu_dpm_force_clock_level(adev, PP_FCLK, mask);
875
876 if (ret)
877 return -EINVAL;
878
879 return count;
880}
881
845static ssize_t amdgpu_get_pp_dpm_pcie(struct device *dev, 882static ssize_t amdgpu_get_pp_dpm_pcie(struct device *dev,
846 struct device_attribute *attr, 883 struct device_attribute *attr,
847 char *buf) 884 char *buf)
@@ -1128,6 +1165,9 @@ static DEVICE_ATTR(pp_dpm_mclk, S_IRUGO | S_IWUSR,
1128static DEVICE_ATTR(pp_dpm_socclk, S_IRUGO | S_IWUSR, 1165static DEVICE_ATTR(pp_dpm_socclk, S_IRUGO | S_IWUSR,
1129 amdgpu_get_pp_dpm_socclk, 1166 amdgpu_get_pp_dpm_socclk,
1130 amdgpu_set_pp_dpm_socclk); 1167 amdgpu_set_pp_dpm_socclk);
1168static DEVICE_ATTR(pp_dpm_fclk, S_IRUGO | S_IWUSR,
1169 amdgpu_get_pp_dpm_fclk,
1170 amdgpu_set_pp_dpm_fclk);
1131static DEVICE_ATTR(pp_dpm_pcie, S_IRUGO | S_IWUSR, 1171static DEVICE_ATTR(pp_dpm_pcie, S_IRUGO | S_IWUSR,
1132 amdgpu_get_pp_dpm_pcie, 1172 amdgpu_get_pp_dpm_pcie,
1133 amdgpu_set_pp_dpm_pcie); 1173 amdgpu_set_pp_dpm_pcie);
@@ -2294,6 +2334,13 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev)
2294 return ret; 2334 return ret;
2295 } 2335 }
2296 } 2336 }
2337 if (adev->asic_type >= CHIP_VEGA20) {
2338 ret = device_create_file(adev->dev, &dev_attr_pp_dpm_fclk);
2339 if (ret) {
2340 DRM_ERROR("failed to create device file pp_dpm_fclk\n");
2341 return ret;
2342 }
2343 }
2297 ret = device_create_file(adev->dev, &dev_attr_pp_dpm_pcie); 2344 ret = device_create_file(adev->dev, &dev_attr_pp_dpm_pcie);
2298 if (ret) { 2345 if (ret) {
2299 DRM_ERROR("failed to create device file pp_dpm_pcie\n"); 2346 DRM_ERROR("failed to create device file pp_dpm_pcie\n");
@@ -2384,6 +2431,8 @@ void amdgpu_pm_sysfs_fini(struct amdgpu_device *adev)
2384 if (adev->asic_type >= CHIP_VEGA10) 2431 if (adev->asic_type >= CHIP_VEGA10)
2385 device_remove_file(adev->dev, &dev_attr_pp_dpm_socclk); 2432 device_remove_file(adev->dev, &dev_attr_pp_dpm_socclk);
2386 device_remove_file(adev->dev, &dev_attr_pp_dpm_pcie); 2433 device_remove_file(adev->dev, &dev_attr_pp_dpm_pcie);
2434 if (adev->asic_type >= CHIP_VEGA20)
2435 device_remove_file(adev->dev, &dev_attr_pp_dpm_fclk);
2387 device_remove_file(adev->dev, &dev_attr_pp_sclk_od); 2436 device_remove_file(adev->dev, &dev_attr_pp_sclk_od);
2388 device_remove_file(adev->dev, &dev_attr_pp_mclk_od); 2437 device_remove_file(adev->dev, &dev_attr_pp_mclk_od);
2389 device_remove_file(adev->dev, 2438 device_remove_file(adev->dev,
diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
index f5ec25a6ab54..f82de14f6560 100644
--- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h
+++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
@@ -93,6 +93,7 @@ enum pp_clock_type {
93 PP_MCLK, 93 PP_MCLK,
94 PP_PCIE, 94 PP_PCIE,
95 PP_SOCCLK, 95 PP_SOCCLK,
96 PP_FCLK,
96 OD_SCLK, 97 OD_SCLK,
97 OD_MCLK, 98 OD_MCLK,
98 OD_VDDC_CURVE, 99 OD_VDDC_CURVE,
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
index e7c890f036fa..4e7399c310e2 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
@@ -1736,6 +1736,17 @@ static int vega20_upload_dpm_min_level(struct pp_hwmgr *hwmgr, uint32_t feature_
1736 return ret); 1736 return ret);
1737 } 1737 }
1738 1738
1739 if (data->smu_features[GNLD_DPM_FCLK].enabled &&
1740 (feature_mask & FEATURE_DPM_FCLK_MASK)) {
1741 min_freq = data->dpm_table.fclk_table.dpm_state.soft_min_level;
1742
1743 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1744 hwmgr, PPSMC_MSG_SetSoftMinByFreq,
1745 (PPCLK_FCLK << 16) | (min_freq & 0xffff))),
1746 "Failed to set soft min fclk!",
1747 return ret);
1748 }
1749
1739 return ret; 1750 return ret;
1740} 1751}
1741 1752
@@ -1808,6 +1819,17 @@ static int vega20_upload_dpm_max_level(struct pp_hwmgr *hwmgr, uint32_t feature_
1808 return ret); 1819 return ret);
1809 } 1820 }
1810 1821
1822 if (data->smu_features[GNLD_DPM_FCLK].enabled &&
1823 (feature_mask & FEATURE_DPM_FCLK_MASK)) {
1824 max_freq = data->dpm_table.fclk_table.dpm_state.soft_max_level;
1825
1826 PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
1827 hwmgr, PPSMC_MSG_SetSoftMaxByFreq,
1828 (PPCLK_FCLK << 16) | (max_freq & 0xffff))),
1829 "Failed to set soft max fclk!",
1830 return ret);
1831 }
1832
1811 return ret; 1833 return ret;
1812} 1834}
1813 1835
@@ -2324,6 +2346,34 @@ static int vega20_force_clock_level(struct pp_hwmgr *hwmgr,
2324 2346
2325 break; 2347 break;
2326 2348
2349 case PP_FCLK:
2350 soft_min_level = mask ? (ffs(mask) - 1) : 0;
2351 soft_max_level = mask ? (fls(mask) - 1) : 0;
2352
2353 if (soft_max_level >= data->dpm_table.fclk_table.count) {
2354 pr_err("Clock level specified %d is over max allowed %d\n",
2355 soft_max_level,
2356 data->dpm_table.fclk_table.count - 1);
2357 return -EINVAL;
2358 }
2359
2360 data->dpm_table.fclk_table.dpm_state.soft_min_level =
2361 data->dpm_table.fclk_table.dpm_levels[soft_min_level].value;
2362 data->dpm_table.fclk_table.dpm_state.soft_max_level =
2363 data->dpm_table.fclk_table.dpm_levels[soft_max_level].value;
2364
2365 ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_FCLK_MASK);
2366 PP_ASSERT_WITH_CODE(!ret,
2367 "Failed to upload boot level to lowest!",
2368 return ret);
2369
2370 ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_FCLK_MASK);
2371 PP_ASSERT_WITH_CODE(!ret,
2372 "Failed to upload dpm max level to highest!",
2373 return ret);
2374
2375 break;
2376
2327 case PP_PCIE: 2377 case PP_PCIE:
2328 soft_min_level = mask ? (ffs(mask) - 1) : 0; 2378 soft_min_level = mask ? (ffs(mask) - 1) : 0;
2329 soft_max_level = mask ? (fls(mask) - 1) : 0; 2379 soft_max_level = mask ? (fls(mask) - 1) : 0;
@@ -2920,6 +2970,8 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr,
2920 PPTable_t *pptable = (PPTable_t *)pptable_information->smc_pptable; 2970 PPTable_t *pptable = (PPTable_t *)pptable_information->smc_pptable;
2921 struct amdgpu_device *adev = hwmgr->adev; 2971 struct amdgpu_device *adev = hwmgr->adev;
2922 struct pp_clock_levels_with_latency clocks; 2972 struct pp_clock_levels_with_latency clocks;
2973 struct vega20_single_dpm_table *fclk_dpm_table =
2974 &(data->dpm_table.fclk_table);
2923 int i, now, size = 0; 2975 int i, now, size = 0;
2924 int ret = 0; 2976 int ret = 0;
2925 uint32_t gen_speed, lane_width; 2977 uint32_t gen_speed, lane_width;
@@ -2976,6 +3028,18 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr,
2976 (clocks.data[i].clocks_in_khz == now * 10) ? "*" : ""); 3028 (clocks.data[i].clocks_in_khz == now * 10) ? "*" : "");
2977 break; 3029 break;
2978 3030
3031 case PP_FCLK:
3032 ret = vega20_get_current_clk_freq(hwmgr, PPCLK_FCLK, &now);
3033 PP_ASSERT_WITH_CODE(!ret,
3034 "Attempt to get current fclk freq Failed!",
3035 return ret);
3036
3037 for (i = 0; i < fclk_dpm_table->count; i++)
3038 size += sprintf(buf + size, "%d: %uMhz %s\n",
3039 i, fclk_dpm_table->dpm_levels[i].value,
3040 fclk_dpm_table->dpm_levels[i].value == (now / 100) ? "*" : "");
3041 break;
3042
2979 case PP_PCIE: 3043 case PP_PCIE:
2980 gen_speed = (RREG32_PCIE(smnPCIE_LC_SPEED_CNTL) & 3044 gen_speed = (RREG32_PCIE(smnPCIE_LC_SPEED_CNTL) &
2981 PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK) 3045 PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK)