18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * Copyright 2012 Advanced Micro Devices, Inc.
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
58c2ecf20Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
68c2ecf20Sopenharmony_ci * to deal in the Software without restriction, including without limitation
78c2ecf20Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
88c2ecf20Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
98c2ecf20Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
108c2ecf20Sopenharmony_ci *
118c2ecf20Sopenharmony_ci * The above copyright notice and this permission notice shall be included in
128c2ecf20Sopenharmony_ci * all copies or substantial portions of the Software.
138c2ecf20Sopenharmony_ci *
148c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
158c2ecf20Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
168c2ecf20Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
178c2ecf20Sopenharmony_ci * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
188c2ecf20Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
198c2ecf20Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
208c2ecf20Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE.
218c2ecf20Sopenharmony_ci *
228c2ecf20Sopenharmony_ci */
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ci#include "radeon.h"
258c2ecf20Sopenharmony_ci#include "trinityd.h"
268c2ecf20Sopenharmony_ci#include "trinity_dpm.h"
278c2ecf20Sopenharmony_ci#include "ppsmc.h"
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_cistatic int trinity_notify_message_to_smu(struct radeon_device *rdev, u32 id)
308c2ecf20Sopenharmony_ci{
318c2ecf20Sopenharmony_ci	int i;
328c2ecf20Sopenharmony_ci	u32 v = 0;
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci	WREG32(SMC_MESSAGE_0, id);
358c2ecf20Sopenharmony_ci	for (i = 0; i < rdev->usec_timeout; i++) {
368c2ecf20Sopenharmony_ci		if (RREG32(SMC_RESP_0) != 0)
378c2ecf20Sopenharmony_ci			break;
388c2ecf20Sopenharmony_ci		udelay(1);
398c2ecf20Sopenharmony_ci	}
408c2ecf20Sopenharmony_ci	v = RREG32(SMC_RESP_0);
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci	if (v != 1) {
438c2ecf20Sopenharmony_ci		if (v == 0xFF) {
448c2ecf20Sopenharmony_ci			DRM_ERROR("SMC failed to handle the message!\n");
458c2ecf20Sopenharmony_ci			return -EINVAL;
468c2ecf20Sopenharmony_ci		} else if (v == 0xFE) {
478c2ecf20Sopenharmony_ci			DRM_ERROR("Unknown SMC message!\n");
488c2ecf20Sopenharmony_ci			return -EINVAL;
498c2ecf20Sopenharmony_ci		}
508c2ecf20Sopenharmony_ci	}
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci	return 0;
538c2ecf20Sopenharmony_ci}
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ciint trinity_dpm_bapm_enable(struct radeon_device *rdev, bool enable)
568c2ecf20Sopenharmony_ci{
578c2ecf20Sopenharmony_ci	if (enable)
588c2ecf20Sopenharmony_ci		return trinity_notify_message_to_smu(rdev, PPSMC_MSG_EnableBAPM);
598c2ecf20Sopenharmony_ci	else
608c2ecf20Sopenharmony_ci		return trinity_notify_message_to_smu(rdev, PPSMC_MSG_DisableBAPM);
618c2ecf20Sopenharmony_ci}
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ciint trinity_dpm_config(struct radeon_device *rdev, bool enable)
648c2ecf20Sopenharmony_ci{
658c2ecf20Sopenharmony_ci	if (enable)
668c2ecf20Sopenharmony_ci		WREG32_SMC(SMU_SCRATCH0, 1);
678c2ecf20Sopenharmony_ci	else
688c2ecf20Sopenharmony_ci		WREG32_SMC(SMU_SCRATCH0, 0);
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci	return trinity_notify_message_to_smu(rdev, PPSMC_MSG_DPM_Config);
718c2ecf20Sopenharmony_ci}
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ciint trinity_dpm_force_state(struct radeon_device *rdev, u32 n)
748c2ecf20Sopenharmony_ci{
758c2ecf20Sopenharmony_ci	WREG32_SMC(SMU_SCRATCH0, n);
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci	return trinity_notify_message_to_smu(rdev, PPSMC_MSG_DPM_ForceState);
788c2ecf20Sopenharmony_ci}
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ciint trinity_dpm_n_levels_disabled(struct radeon_device *rdev, u32 n)
818c2ecf20Sopenharmony_ci{
828c2ecf20Sopenharmony_ci	WREG32_SMC(SMU_SCRATCH0, n);
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci	return trinity_notify_message_to_smu(rdev, PPSMC_MSG_DPM_N_LevelsDisabled);
858c2ecf20Sopenharmony_ci}
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ciint trinity_uvd_dpm_config(struct radeon_device *rdev)
888c2ecf20Sopenharmony_ci{
898c2ecf20Sopenharmony_ci	return trinity_notify_message_to_smu(rdev, PPSMC_MSG_UVD_DPM_Config);
908c2ecf20Sopenharmony_ci}
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ciint trinity_dpm_no_forced_level(struct radeon_device *rdev)
938c2ecf20Sopenharmony_ci{
948c2ecf20Sopenharmony_ci	return trinity_notify_message_to_smu(rdev, PPSMC_MSG_NoForcedLevel);
958c2ecf20Sopenharmony_ci}
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ciint trinity_dce_enable_voltage_adjustment(struct radeon_device *rdev,
988c2ecf20Sopenharmony_ci					  bool enable)
998c2ecf20Sopenharmony_ci{
1008c2ecf20Sopenharmony_ci	if (enable)
1018c2ecf20Sopenharmony_ci		return trinity_notify_message_to_smu(rdev, PPSMC_MSG_DCE_AllowVoltageAdjustment);
1028c2ecf20Sopenharmony_ci	else
1038c2ecf20Sopenharmony_ci		return trinity_notify_message_to_smu(rdev, PPSMC_MSG_DCE_RemoveVoltageAdjustment);
1048c2ecf20Sopenharmony_ci}
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_ciint trinity_gfx_dynamic_mgpg_config(struct radeon_device *rdev)
1078c2ecf20Sopenharmony_ci{
1088c2ecf20Sopenharmony_ci	return trinity_notify_message_to_smu(rdev, PPSMC_MSG_PG_SIMD_Config);
1098c2ecf20Sopenharmony_ci}
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_civoid trinity_acquire_mutex(struct radeon_device *rdev)
1128c2ecf20Sopenharmony_ci{
1138c2ecf20Sopenharmony_ci	int i;
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ci	WREG32(SMC_INT_REQ, 1);
1168c2ecf20Sopenharmony_ci	for (i = 0; i < rdev->usec_timeout; i++) {
1178c2ecf20Sopenharmony_ci		if ((RREG32(SMC_INT_REQ) & 0xffff) == 1)
1188c2ecf20Sopenharmony_ci			break;
1198c2ecf20Sopenharmony_ci		udelay(1);
1208c2ecf20Sopenharmony_ci	}
1218c2ecf20Sopenharmony_ci}
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_civoid trinity_release_mutex(struct radeon_device *rdev)
1248c2ecf20Sopenharmony_ci{
1258c2ecf20Sopenharmony_ci	WREG32(SMC_INT_REQ, 0);
1268c2ecf20Sopenharmony_ci}
127