162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * Copyright 2011 Advanced Micro Devices, Inc.
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
562306a36Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
662306a36Sopenharmony_ci * to deal in the Software without restriction, including without limitation
762306a36Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
862306a36Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
962306a36Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
1062306a36Sopenharmony_ci *
1162306a36Sopenharmony_ci * The above copyright notice and this permission notice shall be included in
1262306a36Sopenharmony_ci * all copies or substantial portions of the Software.
1362306a36Sopenharmony_ci *
1462306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1562306a36Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1662306a36Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1762306a36Sopenharmony_ci * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
1862306a36Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
1962306a36Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2062306a36Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE.
2162306a36Sopenharmony_ci *
2262306a36Sopenharmony_ci * Authors: Alex Deucher
2362306a36Sopenharmony_ci */
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci#include <linux/pci.h>
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci#include "atom.h"
2862306a36Sopenharmony_ci#include "cypress_dpm.h"
2962306a36Sopenharmony_ci#include "evergreen.h"
3062306a36Sopenharmony_ci#include "evergreend.h"
3162306a36Sopenharmony_ci#include "r600_dpm.h"
3262306a36Sopenharmony_ci#include "rv770.h"
3362306a36Sopenharmony_ci#include "radeon.h"
3462306a36Sopenharmony_ci#include "radeon_asic.h"
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci#define SMC_RAM_END 0x8000
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci#define MC_CG_ARB_FREQ_F0           0x0a
3962306a36Sopenharmony_ci#define MC_CG_ARB_FREQ_F1           0x0b
4062306a36Sopenharmony_ci#define MC_CG_ARB_FREQ_F2           0x0c
4162306a36Sopenharmony_ci#define MC_CG_ARB_FREQ_F3           0x0d
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci#define MC_CG_SEQ_DRAMCONF_S0       0x05
4462306a36Sopenharmony_ci#define MC_CG_SEQ_DRAMCONF_S1       0x06
4562306a36Sopenharmony_ci#define MC_CG_SEQ_YCLK_SUSPEND      0x04
4662306a36Sopenharmony_ci#define MC_CG_SEQ_YCLK_RESUME       0x0a
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_cistatic void cypress_enable_bif_dynamic_pcie_gen2(struct radeon_device *rdev,
4962306a36Sopenharmony_ci						 bool enable)
5062306a36Sopenharmony_ci{
5162306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
5262306a36Sopenharmony_ci	u32 tmp, bif;
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci	tmp = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL);
5562306a36Sopenharmony_ci	if (enable) {
5662306a36Sopenharmony_ci		if ((tmp & LC_OTHER_SIDE_EVER_SENT_GEN2) &&
5762306a36Sopenharmony_ci		    (tmp & LC_OTHER_SIDE_SUPPORTS_GEN2)) {
5862306a36Sopenharmony_ci			if (!pi->boot_in_gen2) {
5962306a36Sopenharmony_ci				bif = RREG32(CG_BIF_REQ_AND_RSP) & ~CG_CLIENT_REQ_MASK;
6062306a36Sopenharmony_ci				bif |= CG_CLIENT_REQ(0xd);
6162306a36Sopenharmony_ci				WREG32(CG_BIF_REQ_AND_RSP, bif);
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci				tmp &= ~LC_HW_VOLTAGE_IF_CONTROL_MASK;
6462306a36Sopenharmony_ci				tmp |= LC_HW_VOLTAGE_IF_CONTROL(1);
6562306a36Sopenharmony_ci				tmp |= LC_GEN2_EN_STRAP;
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci				tmp |= LC_CLR_FAILED_SPD_CHANGE_CNT;
6862306a36Sopenharmony_ci				WREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL, tmp);
6962306a36Sopenharmony_ci				udelay(10);
7062306a36Sopenharmony_ci				tmp &= ~LC_CLR_FAILED_SPD_CHANGE_CNT;
7162306a36Sopenharmony_ci				WREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL, tmp);
7262306a36Sopenharmony_ci			}
7362306a36Sopenharmony_ci		}
7462306a36Sopenharmony_ci	} else {
7562306a36Sopenharmony_ci		if (!pi->boot_in_gen2) {
7662306a36Sopenharmony_ci			tmp &= ~LC_HW_VOLTAGE_IF_CONTROL_MASK;
7762306a36Sopenharmony_ci			tmp &= ~LC_GEN2_EN_STRAP;
7862306a36Sopenharmony_ci		}
7962306a36Sopenharmony_ci		if ((tmp & LC_OTHER_SIDE_EVER_SENT_GEN2) ||
8062306a36Sopenharmony_ci		    (tmp & LC_OTHER_SIDE_SUPPORTS_GEN2))
8162306a36Sopenharmony_ci			WREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL, tmp);
8262306a36Sopenharmony_ci	}
8362306a36Sopenharmony_ci}
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_cistatic void cypress_enable_dynamic_pcie_gen2(struct radeon_device *rdev,
8662306a36Sopenharmony_ci					     bool enable)
8762306a36Sopenharmony_ci{
8862306a36Sopenharmony_ci	cypress_enable_bif_dynamic_pcie_gen2(rdev, enable);
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci	if (enable)
9162306a36Sopenharmony_ci		WREG32_P(GENERAL_PWRMGT, ENABLE_GEN2PCIE, ~ENABLE_GEN2PCIE);
9262306a36Sopenharmony_ci	else
9362306a36Sopenharmony_ci		WREG32_P(GENERAL_PWRMGT, 0, ~ENABLE_GEN2PCIE);
9462306a36Sopenharmony_ci}
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci#if 0
9762306a36Sopenharmony_cistatic int cypress_enter_ulp_state(struct radeon_device *rdev)
9862306a36Sopenharmony_ci{
9962306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci	if (pi->gfx_clock_gating) {
10262306a36Sopenharmony_ci		WREG32_P(SCLK_PWRMGT_CNTL, 0, ~DYN_GFX_CLK_OFF_EN);
10362306a36Sopenharmony_ci		WREG32_P(SCLK_PWRMGT_CNTL, GFX_CLK_FORCE_ON, ~GFX_CLK_FORCE_ON);
10462306a36Sopenharmony_ci		WREG32_P(SCLK_PWRMGT_CNTL, 0, ~GFX_CLK_FORCE_ON);
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci		RREG32(GB_ADDR_CONFIG);
10762306a36Sopenharmony_ci	}
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci	WREG32_P(SMC_MSG, HOST_SMC_MSG(PPSMC_MSG_SwitchToMinimumPower),
11062306a36Sopenharmony_ci		 ~HOST_SMC_MSG_MASK);
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci	udelay(7000);
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci	return 0;
11562306a36Sopenharmony_ci}
11662306a36Sopenharmony_ci#endif
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_cistatic void cypress_gfx_clock_gating_enable(struct radeon_device *rdev,
11962306a36Sopenharmony_ci					    bool enable)
12062306a36Sopenharmony_ci{
12162306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci	if (enable) {
12462306a36Sopenharmony_ci		if (eg_pi->light_sleep) {
12562306a36Sopenharmony_ci			WREG32(GRBM_GFX_INDEX, 0xC0000000);
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci			WREG32_CG(CG_CGLS_TILE_0, 0xFFFFFFFF);
12862306a36Sopenharmony_ci			WREG32_CG(CG_CGLS_TILE_1, 0xFFFFFFFF);
12962306a36Sopenharmony_ci			WREG32_CG(CG_CGLS_TILE_2, 0xFFFFFFFF);
13062306a36Sopenharmony_ci			WREG32_CG(CG_CGLS_TILE_3, 0xFFFFFFFF);
13162306a36Sopenharmony_ci			WREG32_CG(CG_CGLS_TILE_4, 0xFFFFFFFF);
13262306a36Sopenharmony_ci			WREG32_CG(CG_CGLS_TILE_5, 0xFFFFFFFF);
13362306a36Sopenharmony_ci			WREG32_CG(CG_CGLS_TILE_6, 0xFFFFFFFF);
13462306a36Sopenharmony_ci			WREG32_CG(CG_CGLS_TILE_7, 0xFFFFFFFF);
13562306a36Sopenharmony_ci			WREG32_CG(CG_CGLS_TILE_8, 0xFFFFFFFF);
13662306a36Sopenharmony_ci			WREG32_CG(CG_CGLS_TILE_9, 0xFFFFFFFF);
13762306a36Sopenharmony_ci			WREG32_CG(CG_CGLS_TILE_10, 0xFFFFFFFF);
13862306a36Sopenharmony_ci			WREG32_CG(CG_CGLS_TILE_11, 0xFFFFFFFF);
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ci			WREG32_P(SCLK_PWRMGT_CNTL, DYN_LIGHT_SLEEP_EN, ~DYN_LIGHT_SLEEP_EN);
14162306a36Sopenharmony_ci		}
14262306a36Sopenharmony_ci		WREG32_P(SCLK_PWRMGT_CNTL, DYN_GFX_CLK_OFF_EN, ~DYN_GFX_CLK_OFF_EN);
14362306a36Sopenharmony_ci	} else {
14462306a36Sopenharmony_ci		WREG32_P(SCLK_PWRMGT_CNTL, 0, ~DYN_GFX_CLK_OFF_EN);
14562306a36Sopenharmony_ci		WREG32_P(SCLK_PWRMGT_CNTL, GFX_CLK_FORCE_ON, ~GFX_CLK_FORCE_ON);
14662306a36Sopenharmony_ci		WREG32_P(SCLK_PWRMGT_CNTL, 0, ~GFX_CLK_FORCE_ON);
14762306a36Sopenharmony_ci		RREG32(GB_ADDR_CONFIG);
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci		if (eg_pi->light_sleep) {
15062306a36Sopenharmony_ci			WREG32_P(SCLK_PWRMGT_CNTL, 0, ~DYN_LIGHT_SLEEP_EN);
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ci			WREG32(GRBM_GFX_INDEX, 0xC0000000);
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_ci			WREG32_CG(CG_CGLS_TILE_0, 0);
15562306a36Sopenharmony_ci			WREG32_CG(CG_CGLS_TILE_1, 0);
15662306a36Sopenharmony_ci			WREG32_CG(CG_CGLS_TILE_2, 0);
15762306a36Sopenharmony_ci			WREG32_CG(CG_CGLS_TILE_3, 0);
15862306a36Sopenharmony_ci			WREG32_CG(CG_CGLS_TILE_4, 0);
15962306a36Sopenharmony_ci			WREG32_CG(CG_CGLS_TILE_5, 0);
16062306a36Sopenharmony_ci			WREG32_CG(CG_CGLS_TILE_6, 0);
16162306a36Sopenharmony_ci			WREG32_CG(CG_CGLS_TILE_7, 0);
16262306a36Sopenharmony_ci			WREG32_CG(CG_CGLS_TILE_8, 0);
16362306a36Sopenharmony_ci			WREG32_CG(CG_CGLS_TILE_9, 0);
16462306a36Sopenharmony_ci			WREG32_CG(CG_CGLS_TILE_10, 0);
16562306a36Sopenharmony_ci			WREG32_CG(CG_CGLS_TILE_11, 0);
16662306a36Sopenharmony_ci		}
16762306a36Sopenharmony_ci	}
16862306a36Sopenharmony_ci}
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_cistatic void cypress_mg_clock_gating_enable(struct radeon_device *rdev,
17162306a36Sopenharmony_ci					   bool enable)
17262306a36Sopenharmony_ci{
17362306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
17462306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci	if (enable) {
17762306a36Sopenharmony_ci		u32 cgts_sm_ctrl_reg;
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_ci		if (rdev->family == CHIP_CEDAR)
18062306a36Sopenharmony_ci			cgts_sm_ctrl_reg = CEDAR_MGCGCGTSSMCTRL_DFLT;
18162306a36Sopenharmony_ci		else if (rdev->family == CHIP_REDWOOD)
18262306a36Sopenharmony_ci			cgts_sm_ctrl_reg = REDWOOD_MGCGCGTSSMCTRL_DFLT;
18362306a36Sopenharmony_ci		else
18462306a36Sopenharmony_ci			cgts_sm_ctrl_reg = CYPRESS_MGCGCGTSSMCTRL_DFLT;
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_ci		WREG32(GRBM_GFX_INDEX, 0xC0000000);
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_ci		WREG32_CG(CG_CGTT_LOCAL_0, CYPRESS_MGCGTTLOCAL0_DFLT);
18962306a36Sopenharmony_ci		WREG32_CG(CG_CGTT_LOCAL_1, CYPRESS_MGCGTTLOCAL1_DFLT & 0xFFFFCFFF);
19062306a36Sopenharmony_ci		WREG32_CG(CG_CGTT_LOCAL_2, CYPRESS_MGCGTTLOCAL2_DFLT);
19162306a36Sopenharmony_ci		WREG32_CG(CG_CGTT_LOCAL_3, CYPRESS_MGCGTTLOCAL3_DFLT);
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_ci		if (pi->mgcgtssm)
19462306a36Sopenharmony_ci			WREG32(CGTS_SM_CTRL_REG, cgts_sm_ctrl_reg);
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_ci		if (eg_pi->mcls) {
19762306a36Sopenharmony_ci			WREG32_P(MC_CITF_MISC_RD_CG, MEM_LS_ENABLE, ~MEM_LS_ENABLE);
19862306a36Sopenharmony_ci			WREG32_P(MC_CITF_MISC_WR_CG, MEM_LS_ENABLE, ~MEM_LS_ENABLE);
19962306a36Sopenharmony_ci			WREG32_P(MC_CITF_MISC_VM_CG, MEM_LS_ENABLE, ~MEM_LS_ENABLE);
20062306a36Sopenharmony_ci			WREG32_P(MC_HUB_MISC_HUB_CG, MEM_LS_ENABLE, ~MEM_LS_ENABLE);
20162306a36Sopenharmony_ci			WREG32_P(MC_HUB_MISC_VM_CG, MEM_LS_ENABLE, ~MEM_LS_ENABLE);
20262306a36Sopenharmony_ci			WREG32_P(MC_HUB_MISC_SIP_CG, MEM_LS_ENABLE, ~MEM_LS_ENABLE);
20362306a36Sopenharmony_ci			WREG32_P(MC_XPB_CLK_GAT, MEM_LS_ENABLE, ~MEM_LS_ENABLE);
20462306a36Sopenharmony_ci			WREG32_P(VM_L2_CG, MEM_LS_ENABLE, ~MEM_LS_ENABLE);
20562306a36Sopenharmony_ci		}
20662306a36Sopenharmony_ci	} else {
20762306a36Sopenharmony_ci		WREG32(GRBM_GFX_INDEX, 0xC0000000);
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci		WREG32_CG(CG_CGTT_LOCAL_0, 0xFFFFFFFF);
21062306a36Sopenharmony_ci		WREG32_CG(CG_CGTT_LOCAL_1, 0xFFFFFFFF);
21162306a36Sopenharmony_ci		WREG32_CG(CG_CGTT_LOCAL_2, 0xFFFFFFFF);
21262306a36Sopenharmony_ci		WREG32_CG(CG_CGTT_LOCAL_3, 0xFFFFFFFF);
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_ci		if (pi->mgcgtssm)
21562306a36Sopenharmony_ci			WREG32(CGTS_SM_CTRL_REG, 0x81f44bc0);
21662306a36Sopenharmony_ci	}
21762306a36Sopenharmony_ci}
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_civoid cypress_enable_spread_spectrum(struct radeon_device *rdev,
22062306a36Sopenharmony_ci				    bool enable)
22162306a36Sopenharmony_ci{
22262306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ci	if (enable) {
22562306a36Sopenharmony_ci		if (pi->sclk_ss)
22662306a36Sopenharmony_ci			WREG32_P(GENERAL_PWRMGT, DYN_SPREAD_SPECTRUM_EN, ~DYN_SPREAD_SPECTRUM_EN);
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_ci		if (pi->mclk_ss)
22962306a36Sopenharmony_ci			WREG32_P(MPLL_CNTL_MODE, SS_SSEN, ~SS_SSEN);
23062306a36Sopenharmony_ci	} else {
23162306a36Sopenharmony_ci		WREG32_P(CG_SPLL_SPREAD_SPECTRUM, 0, ~SSEN);
23262306a36Sopenharmony_ci		WREG32_P(GENERAL_PWRMGT, 0, ~DYN_SPREAD_SPECTRUM_EN);
23362306a36Sopenharmony_ci		WREG32_P(MPLL_CNTL_MODE, 0, ~SS_SSEN);
23462306a36Sopenharmony_ci		WREG32_P(MPLL_CNTL_MODE, 0, ~SS_DSMODE_EN);
23562306a36Sopenharmony_ci	}
23662306a36Sopenharmony_ci}
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_civoid cypress_start_dpm(struct radeon_device *rdev)
23962306a36Sopenharmony_ci{
24062306a36Sopenharmony_ci	WREG32_P(GENERAL_PWRMGT, GLOBAL_PWRMGT_EN, ~GLOBAL_PWRMGT_EN);
24162306a36Sopenharmony_ci}
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_civoid cypress_enable_sclk_control(struct radeon_device *rdev,
24462306a36Sopenharmony_ci				 bool enable)
24562306a36Sopenharmony_ci{
24662306a36Sopenharmony_ci	if (enable)
24762306a36Sopenharmony_ci		WREG32_P(SCLK_PWRMGT_CNTL, 0, ~SCLK_PWRMGT_OFF);
24862306a36Sopenharmony_ci	else
24962306a36Sopenharmony_ci		WREG32_P(SCLK_PWRMGT_CNTL, SCLK_PWRMGT_OFF, ~SCLK_PWRMGT_OFF);
25062306a36Sopenharmony_ci}
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_civoid cypress_enable_mclk_control(struct radeon_device *rdev,
25362306a36Sopenharmony_ci				 bool enable)
25462306a36Sopenharmony_ci{
25562306a36Sopenharmony_ci	if (enable)
25662306a36Sopenharmony_ci		WREG32_P(MCLK_PWRMGT_CNTL, 0, ~MPLL_PWRMGT_OFF);
25762306a36Sopenharmony_ci	else
25862306a36Sopenharmony_ci		WREG32_P(MCLK_PWRMGT_CNTL, MPLL_PWRMGT_OFF, ~MPLL_PWRMGT_OFF);
25962306a36Sopenharmony_ci}
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_ciint cypress_notify_smc_display_change(struct radeon_device *rdev,
26262306a36Sopenharmony_ci				      bool has_display)
26362306a36Sopenharmony_ci{
26462306a36Sopenharmony_ci	PPSMC_Msg msg = has_display ?
26562306a36Sopenharmony_ci		(PPSMC_Msg)PPSMC_MSG_HasDisplay : (PPSMC_Msg)PPSMC_MSG_NoDisplay;
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_ci	if (rv770_send_msg_to_smc(rdev, msg) != PPSMC_Result_OK)
26862306a36Sopenharmony_ci		return -EINVAL;
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_ci	return 0;
27162306a36Sopenharmony_ci}
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_civoid cypress_program_response_times(struct radeon_device *rdev)
27462306a36Sopenharmony_ci{
27562306a36Sopenharmony_ci	u32 reference_clock;
27662306a36Sopenharmony_ci	u32 mclk_switch_limit;
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci	reference_clock = radeon_get_xclk(rdev);
27962306a36Sopenharmony_ci	mclk_switch_limit = (460 * reference_clock) / 100;
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_ci	rv770_write_smc_soft_register(rdev,
28262306a36Sopenharmony_ci				      RV770_SMC_SOFT_REGISTER_mclk_switch_lim,
28362306a36Sopenharmony_ci				      mclk_switch_limit);
28462306a36Sopenharmony_ci
28562306a36Sopenharmony_ci	rv770_write_smc_soft_register(rdev,
28662306a36Sopenharmony_ci				      RV770_SMC_SOFT_REGISTER_mvdd_chg_time, 1);
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_ci	rv770_write_smc_soft_register(rdev,
28962306a36Sopenharmony_ci				      RV770_SMC_SOFT_REGISTER_mc_block_delay, 0xAA);
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_ci	rv770_program_response_times(rdev);
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ci	if (ASIC_IS_LOMBOK(rdev))
29462306a36Sopenharmony_ci		rv770_write_smc_soft_register(rdev,
29562306a36Sopenharmony_ci					      RV770_SMC_SOFT_REGISTER_is_asic_lombok, 1);
29662306a36Sopenharmony_ci
29762306a36Sopenharmony_ci}
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_cistatic int cypress_pcie_performance_request(struct radeon_device *rdev,
30062306a36Sopenharmony_ci					    u8 perf_req, bool advertise)
30162306a36Sopenharmony_ci{
30262306a36Sopenharmony_ci#if defined(CONFIG_ACPI)
30362306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
30462306a36Sopenharmony_ci#endif
30562306a36Sopenharmony_ci	u32 tmp;
30662306a36Sopenharmony_ci
30762306a36Sopenharmony_ci	udelay(10);
30862306a36Sopenharmony_ci	tmp = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL);
30962306a36Sopenharmony_ci	if ((perf_req == PCIE_PERF_REQ_PECI_GEN1) && (tmp & LC_CURRENT_DATA_RATE))
31062306a36Sopenharmony_ci		return 0;
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_ci#if defined(CONFIG_ACPI)
31362306a36Sopenharmony_ci	if ((perf_req == PCIE_PERF_REQ_PECI_GEN1) ||
31462306a36Sopenharmony_ci	    (perf_req == PCIE_PERF_REQ_PECI_GEN2)) {
31562306a36Sopenharmony_ci		eg_pi->pcie_performance_request_registered = true;
31662306a36Sopenharmony_ci		return radeon_acpi_pcie_performance_request(rdev, perf_req, advertise);
31762306a36Sopenharmony_ci	} else if ((perf_req == PCIE_PERF_REQ_REMOVE_REGISTRY) &&
31862306a36Sopenharmony_ci		   eg_pi->pcie_performance_request_registered) {
31962306a36Sopenharmony_ci		eg_pi->pcie_performance_request_registered = false;
32062306a36Sopenharmony_ci		return radeon_acpi_pcie_performance_request(rdev, perf_req, advertise);
32162306a36Sopenharmony_ci	}
32262306a36Sopenharmony_ci#endif
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_ci	return 0;
32562306a36Sopenharmony_ci}
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_civoid cypress_advertise_gen2_capability(struct radeon_device *rdev)
32862306a36Sopenharmony_ci{
32962306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
33062306a36Sopenharmony_ci	u32 tmp;
33162306a36Sopenharmony_ci
33262306a36Sopenharmony_ci#if defined(CONFIG_ACPI)
33362306a36Sopenharmony_ci	radeon_acpi_pcie_notify_device_ready(rdev);
33462306a36Sopenharmony_ci#endif
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_ci	tmp = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL);
33762306a36Sopenharmony_ci
33862306a36Sopenharmony_ci	if ((tmp & LC_OTHER_SIDE_EVER_SENT_GEN2) &&
33962306a36Sopenharmony_ci	    (tmp & LC_OTHER_SIDE_SUPPORTS_GEN2))
34062306a36Sopenharmony_ci		pi->pcie_gen2 = true;
34162306a36Sopenharmony_ci	else
34262306a36Sopenharmony_ci		pi->pcie_gen2 = false;
34362306a36Sopenharmony_ci
34462306a36Sopenharmony_ci	if (!pi->pcie_gen2)
34562306a36Sopenharmony_ci		cypress_pcie_performance_request(rdev, PCIE_PERF_REQ_PECI_GEN2, true);
34662306a36Sopenharmony_ci
34762306a36Sopenharmony_ci}
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_cistatic enum radeon_pcie_gen cypress_get_maximum_link_speed(struct radeon_ps *radeon_state)
35062306a36Sopenharmony_ci{
35162306a36Sopenharmony_ci	struct rv7xx_ps *state = rv770_get_ps(radeon_state);
35262306a36Sopenharmony_ci
35362306a36Sopenharmony_ci	if (state->high.flags & ATOM_PPLIB_R600_FLAGS_PCIEGEN2)
35462306a36Sopenharmony_ci		return 1;
35562306a36Sopenharmony_ci	return 0;
35662306a36Sopenharmony_ci}
35762306a36Sopenharmony_ci
35862306a36Sopenharmony_civoid cypress_notify_link_speed_change_after_state_change(struct radeon_device *rdev,
35962306a36Sopenharmony_ci							 struct radeon_ps *radeon_new_state,
36062306a36Sopenharmony_ci							 struct radeon_ps *radeon_current_state)
36162306a36Sopenharmony_ci{
36262306a36Sopenharmony_ci	enum radeon_pcie_gen pcie_link_speed_target =
36362306a36Sopenharmony_ci		cypress_get_maximum_link_speed(radeon_new_state);
36462306a36Sopenharmony_ci	enum radeon_pcie_gen pcie_link_speed_current =
36562306a36Sopenharmony_ci		cypress_get_maximum_link_speed(radeon_current_state);
36662306a36Sopenharmony_ci	u8 request;
36762306a36Sopenharmony_ci
36862306a36Sopenharmony_ci	if (pcie_link_speed_target < pcie_link_speed_current) {
36962306a36Sopenharmony_ci		if (pcie_link_speed_target == RADEON_PCIE_GEN1)
37062306a36Sopenharmony_ci			request = PCIE_PERF_REQ_PECI_GEN1;
37162306a36Sopenharmony_ci		else if (pcie_link_speed_target == RADEON_PCIE_GEN2)
37262306a36Sopenharmony_ci			request = PCIE_PERF_REQ_PECI_GEN2;
37362306a36Sopenharmony_ci		else
37462306a36Sopenharmony_ci			request = PCIE_PERF_REQ_PECI_GEN3;
37562306a36Sopenharmony_ci
37662306a36Sopenharmony_ci		cypress_pcie_performance_request(rdev, request, false);
37762306a36Sopenharmony_ci	}
37862306a36Sopenharmony_ci}
37962306a36Sopenharmony_ci
38062306a36Sopenharmony_civoid cypress_notify_link_speed_change_before_state_change(struct radeon_device *rdev,
38162306a36Sopenharmony_ci							  struct radeon_ps *radeon_new_state,
38262306a36Sopenharmony_ci							  struct radeon_ps *radeon_current_state)
38362306a36Sopenharmony_ci{
38462306a36Sopenharmony_ci	enum radeon_pcie_gen pcie_link_speed_target =
38562306a36Sopenharmony_ci		cypress_get_maximum_link_speed(radeon_new_state);
38662306a36Sopenharmony_ci	enum radeon_pcie_gen pcie_link_speed_current =
38762306a36Sopenharmony_ci		cypress_get_maximum_link_speed(radeon_current_state);
38862306a36Sopenharmony_ci	u8 request;
38962306a36Sopenharmony_ci
39062306a36Sopenharmony_ci	if (pcie_link_speed_target > pcie_link_speed_current) {
39162306a36Sopenharmony_ci		if (pcie_link_speed_target == RADEON_PCIE_GEN1)
39262306a36Sopenharmony_ci			request = PCIE_PERF_REQ_PECI_GEN1;
39362306a36Sopenharmony_ci		else if (pcie_link_speed_target == RADEON_PCIE_GEN2)
39462306a36Sopenharmony_ci			request = PCIE_PERF_REQ_PECI_GEN2;
39562306a36Sopenharmony_ci		else
39662306a36Sopenharmony_ci			request = PCIE_PERF_REQ_PECI_GEN3;
39762306a36Sopenharmony_ci
39862306a36Sopenharmony_ci		cypress_pcie_performance_request(rdev, request, false);
39962306a36Sopenharmony_ci	}
40062306a36Sopenharmony_ci}
40162306a36Sopenharmony_ci
40262306a36Sopenharmony_cistatic int cypress_populate_voltage_value(struct radeon_device *rdev,
40362306a36Sopenharmony_ci					  struct atom_voltage_table *table,
40462306a36Sopenharmony_ci					  u16 value, RV770_SMC_VOLTAGE_VALUE *voltage)
40562306a36Sopenharmony_ci{
40662306a36Sopenharmony_ci	unsigned int i;
40762306a36Sopenharmony_ci
40862306a36Sopenharmony_ci	for (i = 0; i < table->count; i++) {
40962306a36Sopenharmony_ci		if (value <= table->entries[i].value) {
41062306a36Sopenharmony_ci			voltage->index = (u8)i;
41162306a36Sopenharmony_ci			voltage->value = cpu_to_be16(table->entries[i].value);
41262306a36Sopenharmony_ci			break;
41362306a36Sopenharmony_ci		}
41462306a36Sopenharmony_ci	}
41562306a36Sopenharmony_ci
41662306a36Sopenharmony_ci	if (i == table->count)
41762306a36Sopenharmony_ci		return -EINVAL;
41862306a36Sopenharmony_ci
41962306a36Sopenharmony_ci	return 0;
42062306a36Sopenharmony_ci}
42162306a36Sopenharmony_ci
42262306a36Sopenharmony_ciu8 cypress_get_strobe_mode_settings(struct radeon_device *rdev, u32 mclk)
42362306a36Sopenharmony_ci{
42462306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
42562306a36Sopenharmony_ci	u8 result = 0;
42662306a36Sopenharmony_ci	bool strobe_mode = false;
42762306a36Sopenharmony_ci
42862306a36Sopenharmony_ci	if (pi->mem_gddr5) {
42962306a36Sopenharmony_ci		if (mclk <= pi->mclk_strobe_mode_threshold)
43062306a36Sopenharmony_ci			strobe_mode = true;
43162306a36Sopenharmony_ci		result = cypress_get_mclk_frequency_ratio(rdev, mclk, strobe_mode);
43262306a36Sopenharmony_ci
43362306a36Sopenharmony_ci		if (strobe_mode)
43462306a36Sopenharmony_ci			result |= SMC_STROBE_ENABLE;
43562306a36Sopenharmony_ci	}
43662306a36Sopenharmony_ci
43762306a36Sopenharmony_ci	return result;
43862306a36Sopenharmony_ci}
43962306a36Sopenharmony_ci
44062306a36Sopenharmony_ciu32 cypress_map_clkf_to_ibias(struct radeon_device *rdev, u32 clkf)
44162306a36Sopenharmony_ci{
44262306a36Sopenharmony_ci	u32 ref_clk = rdev->clock.mpll.reference_freq;
44362306a36Sopenharmony_ci	u32 vco = clkf * ref_clk;
44462306a36Sopenharmony_ci
44562306a36Sopenharmony_ci	/* 100 Mhz ref clk */
44662306a36Sopenharmony_ci	if (ref_clk == 10000) {
44762306a36Sopenharmony_ci		if (vco > 500000)
44862306a36Sopenharmony_ci			return 0xC6;
44962306a36Sopenharmony_ci		if (vco > 400000)
45062306a36Sopenharmony_ci			return 0x9D;
45162306a36Sopenharmony_ci		if (vco > 330000)
45262306a36Sopenharmony_ci			return 0x6C;
45362306a36Sopenharmony_ci		if (vco > 250000)
45462306a36Sopenharmony_ci			return 0x2B;
45562306a36Sopenharmony_ci		if (vco >  160000)
45662306a36Sopenharmony_ci			return 0x5B;
45762306a36Sopenharmony_ci		if (vco > 120000)
45862306a36Sopenharmony_ci			return 0x0A;
45962306a36Sopenharmony_ci		return 0x4B;
46062306a36Sopenharmony_ci	}
46162306a36Sopenharmony_ci
46262306a36Sopenharmony_ci	/* 27 Mhz ref clk */
46362306a36Sopenharmony_ci	if (vco > 250000)
46462306a36Sopenharmony_ci		return 0x8B;
46562306a36Sopenharmony_ci	if (vco > 200000)
46662306a36Sopenharmony_ci		return 0xCC;
46762306a36Sopenharmony_ci	if (vco > 150000)
46862306a36Sopenharmony_ci		return 0x9B;
46962306a36Sopenharmony_ci	return 0x6B;
47062306a36Sopenharmony_ci}
47162306a36Sopenharmony_ci
47262306a36Sopenharmony_cistatic int cypress_populate_mclk_value(struct radeon_device *rdev,
47362306a36Sopenharmony_ci				       u32 engine_clock, u32 memory_clock,
47462306a36Sopenharmony_ci				       RV7XX_SMC_MCLK_VALUE *mclk,
47562306a36Sopenharmony_ci				       bool strobe_mode, bool dll_state_on)
47662306a36Sopenharmony_ci{
47762306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
47862306a36Sopenharmony_ci
47962306a36Sopenharmony_ci	u32 mpll_ad_func_cntl =
48062306a36Sopenharmony_ci		pi->clk_regs.rv770.mpll_ad_func_cntl;
48162306a36Sopenharmony_ci	u32 mpll_ad_func_cntl_2 =
48262306a36Sopenharmony_ci		pi->clk_regs.rv770.mpll_ad_func_cntl_2;
48362306a36Sopenharmony_ci	u32 mpll_dq_func_cntl =
48462306a36Sopenharmony_ci		pi->clk_regs.rv770.mpll_dq_func_cntl;
48562306a36Sopenharmony_ci	u32 mpll_dq_func_cntl_2 =
48662306a36Sopenharmony_ci		pi->clk_regs.rv770.mpll_dq_func_cntl_2;
48762306a36Sopenharmony_ci	u32 mclk_pwrmgt_cntl =
48862306a36Sopenharmony_ci		pi->clk_regs.rv770.mclk_pwrmgt_cntl;
48962306a36Sopenharmony_ci	u32 dll_cntl =
49062306a36Sopenharmony_ci		pi->clk_regs.rv770.dll_cntl;
49162306a36Sopenharmony_ci	u32 mpll_ss1 = pi->clk_regs.rv770.mpll_ss1;
49262306a36Sopenharmony_ci	u32 mpll_ss2 = pi->clk_regs.rv770.mpll_ss2;
49362306a36Sopenharmony_ci	struct atom_clock_dividers dividers;
49462306a36Sopenharmony_ci	u32 ibias;
49562306a36Sopenharmony_ci	u32 dll_speed;
49662306a36Sopenharmony_ci	int ret;
49762306a36Sopenharmony_ci	u32 mc_seq_misc7;
49862306a36Sopenharmony_ci
49962306a36Sopenharmony_ci	ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_MEMORY_PLL_PARAM,
50062306a36Sopenharmony_ci					     memory_clock, strobe_mode, &dividers);
50162306a36Sopenharmony_ci	if (ret)
50262306a36Sopenharmony_ci		return ret;
50362306a36Sopenharmony_ci
50462306a36Sopenharmony_ci	if (!strobe_mode) {
50562306a36Sopenharmony_ci		mc_seq_misc7 = RREG32(MC_SEQ_MISC7);
50662306a36Sopenharmony_ci
50762306a36Sopenharmony_ci		if(mc_seq_misc7 & 0x8000000)
50862306a36Sopenharmony_ci			dividers.post_div = 1;
50962306a36Sopenharmony_ci	}
51062306a36Sopenharmony_ci
51162306a36Sopenharmony_ci	ibias = cypress_map_clkf_to_ibias(rdev, dividers.whole_fb_div);
51262306a36Sopenharmony_ci
51362306a36Sopenharmony_ci	mpll_ad_func_cntl &= ~(CLKR_MASK |
51462306a36Sopenharmony_ci			       YCLK_POST_DIV_MASK |
51562306a36Sopenharmony_ci			       CLKF_MASK |
51662306a36Sopenharmony_ci			       CLKFRAC_MASK |
51762306a36Sopenharmony_ci			       IBIAS_MASK);
51862306a36Sopenharmony_ci	mpll_ad_func_cntl |= CLKR(dividers.ref_div);
51962306a36Sopenharmony_ci	mpll_ad_func_cntl |= YCLK_POST_DIV(dividers.post_div);
52062306a36Sopenharmony_ci	mpll_ad_func_cntl |= CLKF(dividers.whole_fb_div);
52162306a36Sopenharmony_ci	mpll_ad_func_cntl |= CLKFRAC(dividers.frac_fb_div);
52262306a36Sopenharmony_ci	mpll_ad_func_cntl |= IBIAS(ibias);
52362306a36Sopenharmony_ci
52462306a36Sopenharmony_ci	if (dividers.vco_mode)
52562306a36Sopenharmony_ci		mpll_ad_func_cntl_2 |= VCO_MODE;
52662306a36Sopenharmony_ci	else
52762306a36Sopenharmony_ci		mpll_ad_func_cntl_2 &= ~VCO_MODE;
52862306a36Sopenharmony_ci
52962306a36Sopenharmony_ci	if (pi->mem_gddr5) {
53062306a36Sopenharmony_ci		mpll_dq_func_cntl &= ~(CLKR_MASK |
53162306a36Sopenharmony_ci				       YCLK_POST_DIV_MASK |
53262306a36Sopenharmony_ci				       CLKF_MASK |
53362306a36Sopenharmony_ci				       CLKFRAC_MASK |
53462306a36Sopenharmony_ci				       IBIAS_MASK);
53562306a36Sopenharmony_ci		mpll_dq_func_cntl |= CLKR(dividers.ref_div);
53662306a36Sopenharmony_ci		mpll_dq_func_cntl |= YCLK_POST_DIV(dividers.post_div);
53762306a36Sopenharmony_ci		mpll_dq_func_cntl |= CLKF(dividers.whole_fb_div);
53862306a36Sopenharmony_ci		mpll_dq_func_cntl |= CLKFRAC(dividers.frac_fb_div);
53962306a36Sopenharmony_ci		mpll_dq_func_cntl |= IBIAS(ibias);
54062306a36Sopenharmony_ci
54162306a36Sopenharmony_ci		if (strobe_mode)
54262306a36Sopenharmony_ci			mpll_dq_func_cntl &= ~PDNB;
54362306a36Sopenharmony_ci		else
54462306a36Sopenharmony_ci			mpll_dq_func_cntl |= PDNB;
54562306a36Sopenharmony_ci
54662306a36Sopenharmony_ci		if (dividers.vco_mode)
54762306a36Sopenharmony_ci			mpll_dq_func_cntl_2 |= VCO_MODE;
54862306a36Sopenharmony_ci		else
54962306a36Sopenharmony_ci			mpll_dq_func_cntl_2 &= ~VCO_MODE;
55062306a36Sopenharmony_ci	}
55162306a36Sopenharmony_ci
55262306a36Sopenharmony_ci	if (pi->mclk_ss) {
55362306a36Sopenharmony_ci		struct radeon_atom_ss ss;
55462306a36Sopenharmony_ci		u32 vco_freq = memory_clock * dividers.post_div;
55562306a36Sopenharmony_ci
55662306a36Sopenharmony_ci		if (radeon_atombios_get_asic_ss_info(rdev, &ss,
55762306a36Sopenharmony_ci						     ASIC_INTERNAL_MEMORY_SS, vco_freq)) {
55862306a36Sopenharmony_ci			u32 reference_clock = rdev->clock.mpll.reference_freq;
55962306a36Sopenharmony_ci			u32 decoded_ref = rv740_get_decoded_reference_divider(dividers.ref_div);
56062306a36Sopenharmony_ci			u32 clk_s, clk_v;
56162306a36Sopenharmony_ci
56262306a36Sopenharmony_ci			if (!decoded_ref)
56362306a36Sopenharmony_ci				return -EINVAL;
56462306a36Sopenharmony_ci			clk_s = reference_clock * 5 / (decoded_ref * ss.rate);
56562306a36Sopenharmony_ci			clk_v = ss.percentage *
56662306a36Sopenharmony_ci				(0x4000 * dividers.whole_fb_div + 0x800 * dividers.frac_fb_div) / (clk_s * 625);
56762306a36Sopenharmony_ci
56862306a36Sopenharmony_ci			mpll_ss1 &= ~CLKV_MASK;
56962306a36Sopenharmony_ci			mpll_ss1 |= CLKV(clk_v);
57062306a36Sopenharmony_ci
57162306a36Sopenharmony_ci			mpll_ss2 &= ~CLKS_MASK;
57262306a36Sopenharmony_ci			mpll_ss2 |= CLKS(clk_s);
57362306a36Sopenharmony_ci		}
57462306a36Sopenharmony_ci	}
57562306a36Sopenharmony_ci
57662306a36Sopenharmony_ci	dll_speed = rv740_get_dll_speed(pi->mem_gddr5,
57762306a36Sopenharmony_ci					memory_clock);
57862306a36Sopenharmony_ci
57962306a36Sopenharmony_ci	mclk_pwrmgt_cntl &= ~DLL_SPEED_MASK;
58062306a36Sopenharmony_ci	mclk_pwrmgt_cntl |= DLL_SPEED(dll_speed);
58162306a36Sopenharmony_ci	if (dll_state_on)
58262306a36Sopenharmony_ci		mclk_pwrmgt_cntl |= (MRDCKA0_PDNB |
58362306a36Sopenharmony_ci				     MRDCKA1_PDNB |
58462306a36Sopenharmony_ci				     MRDCKB0_PDNB |
58562306a36Sopenharmony_ci				     MRDCKB1_PDNB |
58662306a36Sopenharmony_ci				     MRDCKC0_PDNB |
58762306a36Sopenharmony_ci				     MRDCKC1_PDNB |
58862306a36Sopenharmony_ci				     MRDCKD0_PDNB |
58962306a36Sopenharmony_ci				     MRDCKD1_PDNB);
59062306a36Sopenharmony_ci	else
59162306a36Sopenharmony_ci		mclk_pwrmgt_cntl &= ~(MRDCKA0_PDNB |
59262306a36Sopenharmony_ci				      MRDCKA1_PDNB |
59362306a36Sopenharmony_ci				      MRDCKB0_PDNB |
59462306a36Sopenharmony_ci				      MRDCKB1_PDNB |
59562306a36Sopenharmony_ci				      MRDCKC0_PDNB |
59662306a36Sopenharmony_ci				      MRDCKC1_PDNB |
59762306a36Sopenharmony_ci				      MRDCKD0_PDNB |
59862306a36Sopenharmony_ci				      MRDCKD1_PDNB);
59962306a36Sopenharmony_ci
60062306a36Sopenharmony_ci	mclk->mclk770.mclk_value = cpu_to_be32(memory_clock);
60162306a36Sopenharmony_ci	mclk->mclk770.vMPLL_AD_FUNC_CNTL = cpu_to_be32(mpll_ad_func_cntl);
60262306a36Sopenharmony_ci	mclk->mclk770.vMPLL_AD_FUNC_CNTL_2 = cpu_to_be32(mpll_ad_func_cntl_2);
60362306a36Sopenharmony_ci	mclk->mclk770.vMPLL_DQ_FUNC_CNTL = cpu_to_be32(mpll_dq_func_cntl);
60462306a36Sopenharmony_ci	mclk->mclk770.vMPLL_DQ_FUNC_CNTL_2 = cpu_to_be32(mpll_dq_func_cntl_2);
60562306a36Sopenharmony_ci	mclk->mclk770.vMCLK_PWRMGT_CNTL = cpu_to_be32(mclk_pwrmgt_cntl);
60662306a36Sopenharmony_ci	mclk->mclk770.vDLL_CNTL = cpu_to_be32(dll_cntl);
60762306a36Sopenharmony_ci	mclk->mclk770.vMPLL_SS = cpu_to_be32(mpll_ss1);
60862306a36Sopenharmony_ci	mclk->mclk770.vMPLL_SS2 = cpu_to_be32(mpll_ss2);
60962306a36Sopenharmony_ci
61062306a36Sopenharmony_ci	return 0;
61162306a36Sopenharmony_ci}
61262306a36Sopenharmony_ci
61362306a36Sopenharmony_ciu8 cypress_get_mclk_frequency_ratio(struct radeon_device *rdev,
61462306a36Sopenharmony_ci				    u32 memory_clock, bool strobe_mode)
61562306a36Sopenharmony_ci{
61662306a36Sopenharmony_ci	u8 mc_para_index;
61762306a36Sopenharmony_ci
61862306a36Sopenharmony_ci	if (rdev->family >= CHIP_BARTS) {
61962306a36Sopenharmony_ci		if (strobe_mode) {
62062306a36Sopenharmony_ci			if (memory_clock < 10000)
62162306a36Sopenharmony_ci				mc_para_index = 0x00;
62262306a36Sopenharmony_ci			else if (memory_clock > 47500)
62362306a36Sopenharmony_ci				mc_para_index = 0x0f;
62462306a36Sopenharmony_ci			else
62562306a36Sopenharmony_ci				mc_para_index = (u8)((memory_clock - 10000) / 2500);
62662306a36Sopenharmony_ci		} else {
62762306a36Sopenharmony_ci			if (memory_clock < 65000)
62862306a36Sopenharmony_ci				mc_para_index = 0x00;
62962306a36Sopenharmony_ci			else if (memory_clock > 135000)
63062306a36Sopenharmony_ci				mc_para_index = 0x0f;
63162306a36Sopenharmony_ci			else
63262306a36Sopenharmony_ci				mc_para_index = (u8)((memory_clock - 60000) / 5000);
63362306a36Sopenharmony_ci		}
63462306a36Sopenharmony_ci	} else {
63562306a36Sopenharmony_ci		if (strobe_mode) {
63662306a36Sopenharmony_ci			if (memory_clock < 10000)
63762306a36Sopenharmony_ci				mc_para_index = 0x00;
63862306a36Sopenharmony_ci			else if (memory_clock > 47500)
63962306a36Sopenharmony_ci				mc_para_index = 0x0f;
64062306a36Sopenharmony_ci			else
64162306a36Sopenharmony_ci				mc_para_index = (u8)((memory_clock - 10000) / 2500);
64262306a36Sopenharmony_ci		} else {
64362306a36Sopenharmony_ci			if (memory_clock < 40000)
64462306a36Sopenharmony_ci				mc_para_index = 0x00;
64562306a36Sopenharmony_ci			else if (memory_clock > 115000)
64662306a36Sopenharmony_ci				mc_para_index = 0x0f;
64762306a36Sopenharmony_ci			else
64862306a36Sopenharmony_ci				mc_para_index = (u8)((memory_clock - 40000) / 5000);
64962306a36Sopenharmony_ci		}
65062306a36Sopenharmony_ci	}
65162306a36Sopenharmony_ci	return mc_para_index;
65262306a36Sopenharmony_ci}
65362306a36Sopenharmony_ci
65462306a36Sopenharmony_cistatic int cypress_populate_mvdd_value(struct radeon_device *rdev,
65562306a36Sopenharmony_ci				       u32 mclk,
65662306a36Sopenharmony_ci				       RV770_SMC_VOLTAGE_VALUE *voltage)
65762306a36Sopenharmony_ci{
65862306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
65962306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
66062306a36Sopenharmony_ci
66162306a36Sopenharmony_ci	if (!pi->mvdd_control) {
66262306a36Sopenharmony_ci		voltage->index = eg_pi->mvdd_high_index;
66362306a36Sopenharmony_ci		voltage->value = cpu_to_be16(MVDD_HIGH_VALUE);
66462306a36Sopenharmony_ci		return 0;
66562306a36Sopenharmony_ci	}
66662306a36Sopenharmony_ci
66762306a36Sopenharmony_ci	if (mclk <= pi->mvdd_split_frequency) {
66862306a36Sopenharmony_ci		voltage->index = eg_pi->mvdd_low_index;
66962306a36Sopenharmony_ci		voltage->value = cpu_to_be16(MVDD_LOW_VALUE);
67062306a36Sopenharmony_ci	} else {
67162306a36Sopenharmony_ci		voltage->index = eg_pi->mvdd_high_index;
67262306a36Sopenharmony_ci		voltage->value = cpu_to_be16(MVDD_HIGH_VALUE);
67362306a36Sopenharmony_ci	}
67462306a36Sopenharmony_ci
67562306a36Sopenharmony_ci	return 0;
67662306a36Sopenharmony_ci}
67762306a36Sopenharmony_ci
67862306a36Sopenharmony_ciint cypress_convert_power_level_to_smc(struct radeon_device *rdev,
67962306a36Sopenharmony_ci				       struct rv7xx_pl *pl,
68062306a36Sopenharmony_ci				       RV770_SMC_HW_PERFORMANCE_LEVEL *level,
68162306a36Sopenharmony_ci				       u8 watermark_level)
68262306a36Sopenharmony_ci{
68362306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
68462306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
68562306a36Sopenharmony_ci	int ret;
68662306a36Sopenharmony_ci	bool dll_state_on;
68762306a36Sopenharmony_ci
68862306a36Sopenharmony_ci	level->gen2PCIE = pi->pcie_gen2 ?
68962306a36Sopenharmony_ci		((pl->flags & ATOM_PPLIB_R600_FLAGS_PCIEGEN2) ? 1 : 0) : 0;
69062306a36Sopenharmony_ci	level->gen2XSP  = (pl->flags & ATOM_PPLIB_R600_FLAGS_PCIEGEN2) ? 1 : 0;
69162306a36Sopenharmony_ci	level->backbias = (pl->flags & ATOM_PPLIB_R600_FLAGS_BACKBIASENABLE) ? 1 : 0;
69262306a36Sopenharmony_ci	level->displayWatermark = watermark_level;
69362306a36Sopenharmony_ci
69462306a36Sopenharmony_ci	ret = rv740_populate_sclk_value(rdev, pl->sclk, &level->sclk);
69562306a36Sopenharmony_ci	if (ret)
69662306a36Sopenharmony_ci		return ret;
69762306a36Sopenharmony_ci
69862306a36Sopenharmony_ci	level->mcFlags =  0;
69962306a36Sopenharmony_ci	if (pi->mclk_stutter_mode_threshold &&
70062306a36Sopenharmony_ci	    (pl->mclk <= pi->mclk_stutter_mode_threshold) &&
70162306a36Sopenharmony_ci	    !eg_pi->uvd_enabled) {
70262306a36Sopenharmony_ci		level->mcFlags |= SMC_MC_STUTTER_EN;
70362306a36Sopenharmony_ci		if (eg_pi->sclk_deep_sleep)
70462306a36Sopenharmony_ci			level->stateFlags |= PPSMC_STATEFLAG_AUTO_PULSE_SKIP;
70562306a36Sopenharmony_ci		else
70662306a36Sopenharmony_ci			level->stateFlags &= ~PPSMC_STATEFLAG_AUTO_PULSE_SKIP;
70762306a36Sopenharmony_ci	}
70862306a36Sopenharmony_ci
70962306a36Sopenharmony_ci	if (pi->mem_gddr5) {
71062306a36Sopenharmony_ci		if (pl->mclk > pi->mclk_edc_enable_threshold)
71162306a36Sopenharmony_ci			level->mcFlags |= SMC_MC_EDC_RD_FLAG;
71262306a36Sopenharmony_ci
71362306a36Sopenharmony_ci		if (pl->mclk > eg_pi->mclk_edc_wr_enable_threshold)
71462306a36Sopenharmony_ci			level->mcFlags |= SMC_MC_EDC_WR_FLAG;
71562306a36Sopenharmony_ci
71662306a36Sopenharmony_ci		level->strobeMode = cypress_get_strobe_mode_settings(rdev, pl->mclk);
71762306a36Sopenharmony_ci
71862306a36Sopenharmony_ci		if (level->strobeMode & SMC_STROBE_ENABLE) {
71962306a36Sopenharmony_ci			if (cypress_get_mclk_frequency_ratio(rdev, pl->mclk, true) >=
72062306a36Sopenharmony_ci			    ((RREG32(MC_SEQ_MISC7) >> 16) & 0xf))
72162306a36Sopenharmony_ci				dll_state_on = ((RREG32(MC_SEQ_MISC5) >> 1) & 0x1) ? true : false;
72262306a36Sopenharmony_ci			else
72362306a36Sopenharmony_ci				dll_state_on = ((RREG32(MC_SEQ_MISC6) >> 1) & 0x1) ? true : false;
72462306a36Sopenharmony_ci		} else
72562306a36Sopenharmony_ci			dll_state_on = eg_pi->dll_default_on;
72662306a36Sopenharmony_ci
72762306a36Sopenharmony_ci		ret = cypress_populate_mclk_value(rdev,
72862306a36Sopenharmony_ci						  pl->sclk,
72962306a36Sopenharmony_ci						  pl->mclk,
73062306a36Sopenharmony_ci						  &level->mclk,
73162306a36Sopenharmony_ci						  (level->strobeMode & SMC_STROBE_ENABLE) != 0,
73262306a36Sopenharmony_ci						  dll_state_on);
73362306a36Sopenharmony_ci	} else {
73462306a36Sopenharmony_ci		ret = cypress_populate_mclk_value(rdev,
73562306a36Sopenharmony_ci						  pl->sclk,
73662306a36Sopenharmony_ci						  pl->mclk,
73762306a36Sopenharmony_ci						  &level->mclk,
73862306a36Sopenharmony_ci						  true,
73962306a36Sopenharmony_ci						  true);
74062306a36Sopenharmony_ci	}
74162306a36Sopenharmony_ci	if (ret)
74262306a36Sopenharmony_ci		return ret;
74362306a36Sopenharmony_ci
74462306a36Sopenharmony_ci	ret = cypress_populate_voltage_value(rdev,
74562306a36Sopenharmony_ci					     &eg_pi->vddc_voltage_table,
74662306a36Sopenharmony_ci					     pl->vddc,
74762306a36Sopenharmony_ci					     &level->vddc);
74862306a36Sopenharmony_ci	if (ret)
74962306a36Sopenharmony_ci		return ret;
75062306a36Sopenharmony_ci
75162306a36Sopenharmony_ci	if (eg_pi->vddci_control) {
75262306a36Sopenharmony_ci		ret = cypress_populate_voltage_value(rdev,
75362306a36Sopenharmony_ci						     &eg_pi->vddci_voltage_table,
75462306a36Sopenharmony_ci						     pl->vddci,
75562306a36Sopenharmony_ci						     &level->vddci);
75662306a36Sopenharmony_ci		if (ret)
75762306a36Sopenharmony_ci			return ret;
75862306a36Sopenharmony_ci	}
75962306a36Sopenharmony_ci
76062306a36Sopenharmony_ci	ret = cypress_populate_mvdd_value(rdev, pl->mclk, &level->mvdd);
76162306a36Sopenharmony_ci
76262306a36Sopenharmony_ci	return ret;
76362306a36Sopenharmony_ci}
76462306a36Sopenharmony_ci
76562306a36Sopenharmony_cistatic int cypress_convert_power_state_to_smc(struct radeon_device *rdev,
76662306a36Sopenharmony_ci					      struct radeon_ps *radeon_state,
76762306a36Sopenharmony_ci					      RV770_SMC_SWSTATE *smc_state)
76862306a36Sopenharmony_ci{
76962306a36Sopenharmony_ci	struct rv7xx_ps *state = rv770_get_ps(radeon_state);
77062306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
77162306a36Sopenharmony_ci	int ret;
77262306a36Sopenharmony_ci
77362306a36Sopenharmony_ci	if (!(radeon_state->caps & ATOM_PPLIB_DISALLOW_ON_DC))
77462306a36Sopenharmony_ci		smc_state->flags |= PPSMC_SWSTATE_FLAG_DC;
77562306a36Sopenharmony_ci
77662306a36Sopenharmony_ci	ret = cypress_convert_power_level_to_smc(rdev,
77762306a36Sopenharmony_ci						 &state->low,
77862306a36Sopenharmony_ci						 &smc_state->levels[0],
77962306a36Sopenharmony_ci						 PPSMC_DISPLAY_WATERMARK_LOW);
78062306a36Sopenharmony_ci	if (ret)
78162306a36Sopenharmony_ci		return ret;
78262306a36Sopenharmony_ci
78362306a36Sopenharmony_ci	ret = cypress_convert_power_level_to_smc(rdev,
78462306a36Sopenharmony_ci						 &state->medium,
78562306a36Sopenharmony_ci						 &smc_state->levels[1],
78662306a36Sopenharmony_ci						 PPSMC_DISPLAY_WATERMARK_LOW);
78762306a36Sopenharmony_ci	if (ret)
78862306a36Sopenharmony_ci		return ret;
78962306a36Sopenharmony_ci
79062306a36Sopenharmony_ci	ret = cypress_convert_power_level_to_smc(rdev,
79162306a36Sopenharmony_ci						 &state->high,
79262306a36Sopenharmony_ci						 &smc_state->levels[2],
79362306a36Sopenharmony_ci						 PPSMC_DISPLAY_WATERMARK_HIGH);
79462306a36Sopenharmony_ci	if (ret)
79562306a36Sopenharmony_ci		return ret;
79662306a36Sopenharmony_ci
79762306a36Sopenharmony_ci	smc_state->levels[0].arbValue = MC_CG_ARB_FREQ_F1;
79862306a36Sopenharmony_ci	smc_state->levels[1].arbValue = MC_CG_ARB_FREQ_F2;
79962306a36Sopenharmony_ci	smc_state->levels[2].arbValue = MC_CG_ARB_FREQ_F3;
80062306a36Sopenharmony_ci
80162306a36Sopenharmony_ci	if (eg_pi->dynamic_ac_timing) {
80262306a36Sopenharmony_ci		smc_state->levels[0].ACIndex = 2;
80362306a36Sopenharmony_ci		smc_state->levels[1].ACIndex = 3;
80462306a36Sopenharmony_ci		smc_state->levels[2].ACIndex = 4;
80562306a36Sopenharmony_ci	} else {
80662306a36Sopenharmony_ci		smc_state->levels[0].ACIndex = 0;
80762306a36Sopenharmony_ci		smc_state->levels[1].ACIndex = 0;
80862306a36Sopenharmony_ci		smc_state->levels[2].ACIndex = 0;
80962306a36Sopenharmony_ci	}
81062306a36Sopenharmony_ci
81162306a36Sopenharmony_ci	rv770_populate_smc_sp(rdev, radeon_state, smc_state);
81262306a36Sopenharmony_ci
81362306a36Sopenharmony_ci	return rv770_populate_smc_t(rdev, radeon_state, smc_state);
81462306a36Sopenharmony_ci}
81562306a36Sopenharmony_ci
81662306a36Sopenharmony_cistatic void cypress_convert_mc_registers(struct evergreen_mc_reg_entry *entry,
81762306a36Sopenharmony_ci					 SMC_Evergreen_MCRegisterSet *data,
81862306a36Sopenharmony_ci					 u32 num_entries, u32 valid_flag)
81962306a36Sopenharmony_ci{
82062306a36Sopenharmony_ci	u32 i, j;
82162306a36Sopenharmony_ci
82262306a36Sopenharmony_ci	for (i = 0, j = 0; j < num_entries; j++) {
82362306a36Sopenharmony_ci		if (valid_flag & (1 << j)) {
82462306a36Sopenharmony_ci			data->value[i] = cpu_to_be32(entry->mc_data[j]);
82562306a36Sopenharmony_ci			i++;
82662306a36Sopenharmony_ci		}
82762306a36Sopenharmony_ci	}
82862306a36Sopenharmony_ci}
82962306a36Sopenharmony_ci
83062306a36Sopenharmony_cistatic void cypress_convert_mc_reg_table_entry_to_smc(struct radeon_device *rdev,
83162306a36Sopenharmony_ci						      struct rv7xx_pl *pl,
83262306a36Sopenharmony_ci						      SMC_Evergreen_MCRegisterSet *mc_reg_table_data)
83362306a36Sopenharmony_ci{
83462306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
83562306a36Sopenharmony_ci	u32 i = 0;
83662306a36Sopenharmony_ci
83762306a36Sopenharmony_ci	for (i = 0; i < eg_pi->mc_reg_table.num_entries; i++) {
83862306a36Sopenharmony_ci		if (pl->mclk <=
83962306a36Sopenharmony_ci		    eg_pi->mc_reg_table.mc_reg_table_entry[i].mclk_max)
84062306a36Sopenharmony_ci			break;
84162306a36Sopenharmony_ci	}
84262306a36Sopenharmony_ci
84362306a36Sopenharmony_ci	if ((i == eg_pi->mc_reg_table.num_entries) && (i > 0))
84462306a36Sopenharmony_ci		--i;
84562306a36Sopenharmony_ci
84662306a36Sopenharmony_ci	cypress_convert_mc_registers(&eg_pi->mc_reg_table.mc_reg_table_entry[i],
84762306a36Sopenharmony_ci				     mc_reg_table_data,
84862306a36Sopenharmony_ci				     eg_pi->mc_reg_table.last,
84962306a36Sopenharmony_ci				     eg_pi->mc_reg_table.valid_flag);
85062306a36Sopenharmony_ci}
85162306a36Sopenharmony_ci
85262306a36Sopenharmony_cistatic void cypress_convert_mc_reg_table_to_smc(struct radeon_device *rdev,
85362306a36Sopenharmony_ci						struct radeon_ps *radeon_state,
85462306a36Sopenharmony_ci						SMC_Evergreen_MCRegisters *mc_reg_table)
85562306a36Sopenharmony_ci{
85662306a36Sopenharmony_ci	struct rv7xx_ps *state = rv770_get_ps(radeon_state);
85762306a36Sopenharmony_ci
85862306a36Sopenharmony_ci	cypress_convert_mc_reg_table_entry_to_smc(rdev,
85962306a36Sopenharmony_ci						  &state->low,
86062306a36Sopenharmony_ci						  &mc_reg_table->data[2]);
86162306a36Sopenharmony_ci	cypress_convert_mc_reg_table_entry_to_smc(rdev,
86262306a36Sopenharmony_ci						  &state->medium,
86362306a36Sopenharmony_ci						  &mc_reg_table->data[3]);
86462306a36Sopenharmony_ci	cypress_convert_mc_reg_table_entry_to_smc(rdev,
86562306a36Sopenharmony_ci						  &state->high,
86662306a36Sopenharmony_ci						  &mc_reg_table->data[4]);
86762306a36Sopenharmony_ci}
86862306a36Sopenharmony_ci
86962306a36Sopenharmony_ciint cypress_upload_sw_state(struct radeon_device *rdev,
87062306a36Sopenharmony_ci			    struct radeon_ps *radeon_new_state)
87162306a36Sopenharmony_ci{
87262306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
87362306a36Sopenharmony_ci	u16 address = pi->state_table_start +
87462306a36Sopenharmony_ci		offsetof(RV770_SMC_STATETABLE, driverState);
87562306a36Sopenharmony_ci	RV770_SMC_SWSTATE state = { 0 };
87662306a36Sopenharmony_ci	int ret;
87762306a36Sopenharmony_ci
87862306a36Sopenharmony_ci	ret = cypress_convert_power_state_to_smc(rdev, radeon_new_state, &state);
87962306a36Sopenharmony_ci	if (ret)
88062306a36Sopenharmony_ci		return ret;
88162306a36Sopenharmony_ci
88262306a36Sopenharmony_ci	return rv770_copy_bytes_to_smc(rdev, address, (u8 *)&state,
88362306a36Sopenharmony_ci				    sizeof(RV770_SMC_SWSTATE),
88462306a36Sopenharmony_ci				    pi->sram_end);
88562306a36Sopenharmony_ci}
88662306a36Sopenharmony_ci
88762306a36Sopenharmony_ciint cypress_upload_mc_reg_table(struct radeon_device *rdev,
88862306a36Sopenharmony_ci				struct radeon_ps *radeon_new_state)
88962306a36Sopenharmony_ci{
89062306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
89162306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
89262306a36Sopenharmony_ci	SMC_Evergreen_MCRegisters mc_reg_table = { 0 };
89362306a36Sopenharmony_ci	u16 address;
89462306a36Sopenharmony_ci
89562306a36Sopenharmony_ci	cypress_convert_mc_reg_table_to_smc(rdev, radeon_new_state, &mc_reg_table);
89662306a36Sopenharmony_ci
89762306a36Sopenharmony_ci	address = eg_pi->mc_reg_table_start +
89862306a36Sopenharmony_ci		(u16)offsetof(SMC_Evergreen_MCRegisters, data[2]);
89962306a36Sopenharmony_ci
90062306a36Sopenharmony_ci	return rv770_copy_bytes_to_smc(rdev, address,
90162306a36Sopenharmony_ci				       (u8 *)&mc_reg_table.data[2],
90262306a36Sopenharmony_ci				       sizeof(SMC_Evergreen_MCRegisterSet) * 3,
90362306a36Sopenharmony_ci				       pi->sram_end);
90462306a36Sopenharmony_ci}
90562306a36Sopenharmony_ci
90662306a36Sopenharmony_ciu32 cypress_calculate_burst_time(struct radeon_device *rdev,
90762306a36Sopenharmony_ci				 u32 engine_clock, u32 memory_clock)
90862306a36Sopenharmony_ci{
90962306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
91062306a36Sopenharmony_ci	u32 multiplier = pi->mem_gddr5 ? 1 : 2;
91162306a36Sopenharmony_ci	u32 result = (4 * multiplier * engine_clock) / (memory_clock / 2);
91262306a36Sopenharmony_ci	u32 burst_time;
91362306a36Sopenharmony_ci
91462306a36Sopenharmony_ci	if (result <= 4)
91562306a36Sopenharmony_ci		burst_time = 0;
91662306a36Sopenharmony_ci	else if (result < 8)
91762306a36Sopenharmony_ci		burst_time = result - 4;
91862306a36Sopenharmony_ci	else {
91962306a36Sopenharmony_ci		burst_time = result / 2 ;
92062306a36Sopenharmony_ci		if (burst_time > 18)
92162306a36Sopenharmony_ci			burst_time = 18;
92262306a36Sopenharmony_ci	}
92362306a36Sopenharmony_ci
92462306a36Sopenharmony_ci	return burst_time;
92562306a36Sopenharmony_ci}
92662306a36Sopenharmony_ci
92762306a36Sopenharmony_civoid cypress_program_memory_timing_parameters(struct radeon_device *rdev,
92862306a36Sopenharmony_ci					      struct radeon_ps *radeon_new_state)
92962306a36Sopenharmony_ci{
93062306a36Sopenharmony_ci	struct rv7xx_ps *new_state = rv770_get_ps(radeon_new_state);
93162306a36Sopenharmony_ci	u32 mc_arb_burst_time = RREG32(MC_ARB_BURST_TIME);
93262306a36Sopenharmony_ci
93362306a36Sopenharmony_ci	mc_arb_burst_time &= ~(STATE1_MASK | STATE2_MASK | STATE3_MASK);
93462306a36Sopenharmony_ci
93562306a36Sopenharmony_ci	mc_arb_burst_time |= STATE1(cypress_calculate_burst_time(rdev,
93662306a36Sopenharmony_ci								 new_state->low.sclk,
93762306a36Sopenharmony_ci								 new_state->low.mclk));
93862306a36Sopenharmony_ci	mc_arb_burst_time |= STATE2(cypress_calculate_burst_time(rdev,
93962306a36Sopenharmony_ci								 new_state->medium.sclk,
94062306a36Sopenharmony_ci								 new_state->medium.mclk));
94162306a36Sopenharmony_ci	mc_arb_burst_time |= STATE3(cypress_calculate_burst_time(rdev,
94262306a36Sopenharmony_ci								 new_state->high.sclk,
94362306a36Sopenharmony_ci								 new_state->high.mclk));
94462306a36Sopenharmony_ci
94562306a36Sopenharmony_ci	rv730_program_memory_timing_parameters(rdev, radeon_new_state);
94662306a36Sopenharmony_ci
94762306a36Sopenharmony_ci	WREG32(MC_ARB_BURST_TIME, mc_arb_burst_time);
94862306a36Sopenharmony_ci}
94962306a36Sopenharmony_ci
95062306a36Sopenharmony_cistatic void cypress_populate_mc_reg_addresses(struct radeon_device *rdev,
95162306a36Sopenharmony_ci					      SMC_Evergreen_MCRegisters *mc_reg_table)
95262306a36Sopenharmony_ci{
95362306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
95462306a36Sopenharmony_ci	u32 i, j;
95562306a36Sopenharmony_ci
95662306a36Sopenharmony_ci	for (i = 0, j = 0; j < eg_pi->mc_reg_table.last; j++) {
95762306a36Sopenharmony_ci		if (eg_pi->mc_reg_table.valid_flag & (1 << j)) {
95862306a36Sopenharmony_ci			mc_reg_table->address[i].s0 =
95962306a36Sopenharmony_ci				cpu_to_be16(eg_pi->mc_reg_table.mc_reg_address[j].s0);
96062306a36Sopenharmony_ci			mc_reg_table->address[i].s1 =
96162306a36Sopenharmony_ci				cpu_to_be16(eg_pi->mc_reg_table.mc_reg_address[j].s1);
96262306a36Sopenharmony_ci			i++;
96362306a36Sopenharmony_ci		}
96462306a36Sopenharmony_ci	}
96562306a36Sopenharmony_ci
96662306a36Sopenharmony_ci	mc_reg_table->last = (u8)i;
96762306a36Sopenharmony_ci}
96862306a36Sopenharmony_ci
96962306a36Sopenharmony_cistatic void cypress_set_mc_reg_address_table(struct radeon_device *rdev)
97062306a36Sopenharmony_ci{
97162306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
97262306a36Sopenharmony_ci	u32 i = 0;
97362306a36Sopenharmony_ci
97462306a36Sopenharmony_ci	eg_pi->mc_reg_table.mc_reg_address[i].s0 = MC_SEQ_RAS_TIMING_LP >> 2;
97562306a36Sopenharmony_ci	eg_pi->mc_reg_table.mc_reg_address[i].s1 = MC_SEQ_RAS_TIMING >> 2;
97662306a36Sopenharmony_ci	i++;
97762306a36Sopenharmony_ci
97862306a36Sopenharmony_ci	eg_pi->mc_reg_table.mc_reg_address[i].s0 = MC_SEQ_CAS_TIMING_LP >> 2;
97962306a36Sopenharmony_ci	eg_pi->mc_reg_table.mc_reg_address[i].s1 = MC_SEQ_CAS_TIMING >> 2;
98062306a36Sopenharmony_ci	i++;
98162306a36Sopenharmony_ci
98262306a36Sopenharmony_ci	eg_pi->mc_reg_table.mc_reg_address[i].s0 = MC_SEQ_MISC_TIMING_LP >> 2;
98362306a36Sopenharmony_ci	eg_pi->mc_reg_table.mc_reg_address[i].s1 = MC_SEQ_MISC_TIMING >> 2;
98462306a36Sopenharmony_ci	i++;
98562306a36Sopenharmony_ci
98662306a36Sopenharmony_ci	eg_pi->mc_reg_table.mc_reg_address[i].s0 = MC_SEQ_MISC_TIMING2_LP >> 2;
98762306a36Sopenharmony_ci	eg_pi->mc_reg_table.mc_reg_address[i].s1 = MC_SEQ_MISC_TIMING2 >> 2;
98862306a36Sopenharmony_ci	i++;
98962306a36Sopenharmony_ci
99062306a36Sopenharmony_ci	eg_pi->mc_reg_table.mc_reg_address[i].s0 = MC_SEQ_RD_CTL_D0_LP >> 2;
99162306a36Sopenharmony_ci	eg_pi->mc_reg_table.mc_reg_address[i].s1 = MC_SEQ_RD_CTL_D0 >> 2;
99262306a36Sopenharmony_ci	i++;
99362306a36Sopenharmony_ci
99462306a36Sopenharmony_ci	eg_pi->mc_reg_table.mc_reg_address[i].s0 = MC_SEQ_RD_CTL_D1_LP >> 2;
99562306a36Sopenharmony_ci	eg_pi->mc_reg_table.mc_reg_address[i].s1 = MC_SEQ_RD_CTL_D1 >> 2;
99662306a36Sopenharmony_ci	i++;
99762306a36Sopenharmony_ci
99862306a36Sopenharmony_ci	eg_pi->mc_reg_table.mc_reg_address[i].s0 = MC_SEQ_WR_CTL_D0_LP >> 2;
99962306a36Sopenharmony_ci	eg_pi->mc_reg_table.mc_reg_address[i].s1 = MC_SEQ_WR_CTL_D0 >> 2;
100062306a36Sopenharmony_ci	i++;
100162306a36Sopenharmony_ci
100262306a36Sopenharmony_ci	eg_pi->mc_reg_table.mc_reg_address[i].s0 = MC_SEQ_WR_CTL_D1_LP >> 2;
100362306a36Sopenharmony_ci	eg_pi->mc_reg_table.mc_reg_address[i].s1 = MC_SEQ_WR_CTL_D1 >> 2;
100462306a36Sopenharmony_ci	i++;
100562306a36Sopenharmony_ci
100662306a36Sopenharmony_ci	eg_pi->mc_reg_table.mc_reg_address[i].s0 = MC_SEQ_PMG_CMD_EMRS_LP >> 2;
100762306a36Sopenharmony_ci	eg_pi->mc_reg_table.mc_reg_address[i].s1 = MC_PMG_CMD_EMRS >> 2;
100862306a36Sopenharmony_ci	i++;
100962306a36Sopenharmony_ci
101062306a36Sopenharmony_ci	eg_pi->mc_reg_table.mc_reg_address[i].s0 = MC_SEQ_PMG_CMD_MRS_LP >> 2;
101162306a36Sopenharmony_ci	eg_pi->mc_reg_table.mc_reg_address[i].s1 = MC_PMG_CMD_MRS >> 2;
101262306a36Sopenharmony_ci	i++;
101362306a36Sopenharmony_ci
101462306a36Sopenharmony_ci	eg_pi->mc_reg_table.mc_reg_address[i].s0 = MC_SEQ_PMG_CMD_MRS1_LP >> 2;
101562306a36Sopenharmony_ci	eg_pi->mc_reg_table.mc_reg_address[i].s1 = MC_PMG_CMD_MRS1 >> 2;
101662306a36Sopenharmony_ci	i++;
101762306a36Sopenharmony_ci
101862306a36Sopenharmony_ci	eg_pi->mc_reg_table.mc_reg_address[i].s0 = MC_SEQ_MISC1 >> 2;
101962306a36Sopenharmony_ci	eg_pi->mc_reg_table.mc_reg_address[i].s1 = MC_SEQ_MISC1 >> 2;
102062306a36Sopenharmony_ci	i++;
102162306a36Sopenharmony_ci
102262306a36Sopenharmony_ci	eg_pi->mc_reg_table.mc_reg_address[i].s0 = MC_SEQ_RESERVE_M >> 2;
102362306a36Sopenharmony_ci	eg_pi->mc_reg_table.mc_reg_address[i].s1 = MC_SEQ_RESERVE_M >> 2;
102462306a36Sopenharmony_ci	i++;
102562306a36Sopenharmony_ci
102662306a36Sopenharmony_ci	eg_pi->mc_reg_table.mc_reg_address[i].s0 = MC_SEQ_MISC3 >> 2;
102762306a36Sopenharmony_ci	eg_pi->mc_reg_table.mc_reg_address[i].s1 = MC_SEQ_MISC3 >> 2;
102862306a36Sopenharmony_ci	i++;
102962306a36Sopenharmony_ci
103062306a36Sopenharmony_ci	eg_pi->mc_reg_table.last = (u8)i;
103162306a36Sopenharmony_ci}
103262306a36Sopenharmony_ci
103362306a36Sopenharmony_cistatic void cypress_retrieve_ac_timing_for_one_entry(struct radeon_device *rdev,
103462306a36Sopenharmony_ci						     struct evergreen_mc_reg_entry *entry)
103562306a36Sopenharmony_ci{
103662306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
103762306a36Sopenharmony_ci	u32 i;
103862306a36Sopenharmony_ci
103962306a36Sopenharmony_ci	for (i = 0; i < eg_pi->mc_reg_table.last; i++)
104062306a36Sopenharmony_ci		entry->mc_data[i] =
104162306a36Sopenharmony_ci			RREG32(eg_pi->mc_reg_table.mc_reg_address[i].s1 << 2);
104262306a36Sopenharmony_ci
104362306a36Sopenharmony_ci}
104462306a36Sopenharmony_ci
104562306a36Sopenharmony_cistatic void cypress_retrieve_ac_timing_for_all_ranges(struct radeon_device *rdev,
104662306a36Sopenharmony_ci						      struct atom_memory_clock_range_table *range_table)
104762306a36Sopenharmony_ci{
104862306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
104962306a36Sopenharmony_ci	u32 i, j;
105062306a36Sopenharmony_ci
105162306a36Sopenharmony_ci	for (i = 0; i < range_table->num_entries; i++) {
105262306a36Sopenharmony_ci		eg_pi->mc_reg_table.mc_reg_table_entry[i].mclk_max =
105362306a36Sopenharmony_ci			range_table->mclk[i];
105462306a36Sopenharmony_ci		radeon_atom_set_ac_timing(rdev, range_table->mclk[i]);
105562306a36Sopenharmony_ci		cypress_retrieve_ac_timing_for_one_entry(rdev,
105662306a36Sopenharmony_ci							 &eg_pi->mc_reg_table.mc_reg_table_entry[i]);
105762306a36Sopenharmony_ci	}
105862306a36Sopenharmony_ci
105962306a36Sopenharmony_ci	eg_pi->mc_reg_table.num_entries = range_table->num_entries;
106062306a36Sopenharmony_ci	eg_pi->mc_reg_table.valid_flag = 0;
106162306a36Sopenharmony_ci
106262306a36Sopenharmony_ci	for (i = 0; i < eg_pi->mc_reg_table.last; i++) {
106362306a36Sopenharmony_ci		for (j = 1; j < range_table->num_entries; j++) {
106462306a36Sopenharmony_ci			if (eg_pi->mc_reg_table.mc_reg_table_entry[j-1].mc_data[i] !=
106562306a36Sopenharmony_ci			    eg_pi->mc_reg_table.mc_reg_table_entry[j].mc_data[i]) {
106662306a36Sopenharmony_ci				eg_pi->mc_reg_table.valid_flag |= (1 << i);
106762306a36Sopenharmony_ci				break;
106862306a36Sopenharmony_ci			}
106962306a36Sopenharmony_ci		}
107062306a36Sopenharmony_ci	}
107162306a36Sopenharmony_ci}
107262306a36Sopenharmony_ci
107362306a36Sopenharmony_cistatic int cypress_initialize_mc_reg_table(struct radeon_device *rdev)
107462306a36Sopenharmony_ci{
107562306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
107662306a36Sopenharmony_ci	u8 module_index = rv770_get_memory_module_index(rdev);
107762306a36Sopenharmony_ci	struct atom_memory_clock_range_table range_table = { 0 };
107862306a36Sopenharmony_ci	int ret;
107962306a36Sopenharmony_ci
108062306a36Sopenharmony_ci	ret = radeon_atom_get_mclk_range_table(rdev,
108162306a36Sopenharmony_ci					       pi->mem_gddr5,
108262306a36Sopenharmony_ci					       module_index, &range_table);
108362306a36Sopenharmony_ci	if (ret)
108462306a36Sopenharmony_ci		return ret;
108562306a36Sopenharmony_ci
108662306a36Sopenharmony_ci	cypress_retrieve_ac_timing_for_all_ranges(rdev, &range_table);
108762306a36Sopenharmony_ci
108862306a36Sopenharmony_ci	return 0;
108962306a36Sopenharmony_ci}
109062306a36Sopenharmony_ci
109162306a36Sopenharmony_cistatic void cypress_wait_for_mc_sequencer(struct radeon_device *rdev, u8 value)
109262306a36Sopenharmony_ci{
109362306a36Sopenharmony_ci	u32 i, j;
109462306a36Sopenharmony_ci	u32 channels = 2;
109562306a36Sopenharmony_ci
109662306a36Sopenharmony_ci	if ((rdev->family == CHIP_CYPRESS) ||
109762306a36Sopenharmony_ci	    (rdev->family == CHIP_HEMLOCK))
109862306a36Sopenharmony_ci		channels = 4;
109962306a36Sopenharmony_ci	else if (rdev->family == CHIP_CEDAR)
110062306a36Sopenharmony_ci		channels = 1;
110162306a36Sopenharmony_ci
110262306a36Sopenharmony_ci	for (i = 0; i < channels; i++) {
110362306a36Sopenharmony_ci		if ((rdev->family == CHIP_CYPRESS) ||
110462306a36Sopenharmony_ci		    (rdev->family == CHIP_HEMLOCK)) {
110562306a36Sopenharmony_ci			WREG32_P(MC_CONFIG_MCD, MC_RD_ENABLE_MCD(i), ~MC_RD_ENABLE_MCD_MASK);
110662306a36Sopenharmony_ci			WREG32_P(MC_CG_CONFIG_MCD, MC_RD_ENABLE_MCD(i), ~MC_RD_ENABLE_MCD_MASK);
110762306a36Sopenharmony_ci		} else {
110862306a36Sopenharmony_ci			WREG32_P(MC_CONFIG, MC_RD_ENABLE(i), ~MC_RD_ENABLE_MASK);
110962306a36Sopenharmony_ci			WREG32_P(MC_CG_CONFIG, MC_RD_ENABLE(i), ~MC_RD_ENABLE_MASK);
111062306a36Sopenharmony_ci		}
111162306a36Sopenharmony_ci		for (j = 0; j < rdev->usec_timeout; j++) {
111262306a36Sopenharmony_ci			if (((RREG32(MC_SEQ_CG) & CG_SEQ_RESP_MASK) >> CG_SEQ_RESP_SHIFT) == value)
111362306a36Sopenharmony_ci				break;
111462306a36Sopenharmony_ci			udelay(1);
111562306a36Sopenharmony_ci		}
111662306a36Sopenharmony_ci	}
111762306a36Sopenharmony_ci}
111862306a36Sopenharmony_ci
111962306a36Sopenharmony_cistatic void cypress_force_mc_use_s1(struct radeon_device *rdev,
112062306a36Sopenharmony_ci				    struct radeon_ps *radeon_boot_state)
112162306a36Sopenharmony_ci{
112262306a36Sopenharmony_ci	struct rv7xx_ps *boot_state = rv770_get_ps(radeon_boot_state);
112362306a36Sopenharmony_ci	u32 strobe_mode;
112462306a36Sopenharmony_ci	u32 mc_seq_cg;
112562306a36Sopenharmony_ci	int i;
112662306a36Sopenharmony_ci
112762306a36Sopenharmony_ci	if (RREG32(MC_SEQ_STATUS_M) & PMG_PWRSTATE)
112862306a36Sopenharmony_ci		return;
112962306a36Sopenharmony_ci
113062306a36Sopenharmony_ci	radeon_atom_set_ac_timing(rdev, boot_state->low.mclk);
113162306a36Sopenharmony_ci	radeon_mc_wait_for_idle(rdev);
113262306a36Sopenharmony_ci
113362306a36Sopenharmony_ci	if ((rdev->family == CHIP_CYPRESS) ||
113462306a36Sopenharmony_ci	    (rdev->family == CHIP_HEMLOCK)) {
113562306a36Sopenharmony_ci		WREG32(MC_CONFIG_MCD, 0xf);
113662306a36Sopenharmony_ci		WREG32(MC_CG_CONFIG_MCD, 0xf);
113762306a36Sopenharmony_ci	} else {
113862306a36Sopenharmony_ci		WREG32(MC_CONFIG, 0xf);
113962306a36Sopenharmony_ci		WREG32(MC_CG_CONFIG, 0xf);
114062306a36Sopenharmony_ci	}
114162306a36Sopenharmony_ci
114262306a36Sopenharmony_ci	for (i = 0; i < rdev->num_crtc; i++)
114362306a36Sopenharmony_ci		radeon_wait_for_vblank(rdev, i);
114462306a36Sopenharmony_ci
114562306a36Sopenharmony_ci	WREG32(MC_SEQ_CG, MC_CG_SEQ_YCLK_SUSPEND);
114662306a36Sopenharmony_ci	cypress_wait_for_mc_sequencer(rdev, MC_CG_SEQ_YCLK_SUSPEND);
114762306a36Sopenharmony_ci
114862306a36Sopenharmony_ci	strobe_mode = cypress_get_strobe_mode_settings(rdev,
114962306a36Sopenharmony_ci						       boot_state->low.mclk);
115062306a36Sopenharmony_ci
115162306a36Sopenharmony_ci	mc_seq_cg = CG_SEQ_REQ(MC_CG_SEQ_DRAMCONF_S1);
115262306a36Sopenharmony_ci	mc_seq_cg |= SEQ_CG_RESP(strobe_mode);
115362306a36Sopenharmony_ci	WREG32(MC_SEQ_CG, mc_seq_cg);
115462306a36Sopenharmony_ci
115562306a36Sopenharmony_ci	for (i = 0; i < rdev->usec_timeout; i++) {
115662306a36Sopenharmony_ci		if (RREG32(MC_SEQ_STATUS_M) & PMG_PWRSTATE)
115762306a36Sopenharmony_ci			break;
115862306a36Sopenharmony_ci		udelay(1);
115962306a36Sopenharmony_ci	}
116062306a36Sopenharmony_ci
116162306a36Sopenharmony_ci	mc_seq_cg &= ~CG_SEQ_REQ_MASK;
116262306a36Sopenharmony_ci	mc_seq_cg |= CG_SEQ_REQ(MC_CG_SEQ_YCLK_RESUME);
116362306a36Sopenharmony_ci	WREG32(MC_SEQ_CG, mc_seq_cg);
116462306a36Sopenharmony_ci
116562306a36Sopenharmony_ci	cypress_wait_for_mc_sequencer(rdev, MC_CG_SEQ_YCLK_RESUME);
116662306a36Sopenharmony_ci}
116762306a36Sopenharmony_ci
116862306a36Sopenharmony_cistatic void cypress_copy_ac_timing_from_s1_to_s0(struct radeon_device *rdev)
116962306a36Sopenharmony_ci{
117062306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
117162306a36Sopenharmony_ci	u32 value;
117262306a36Sopenharmony_ci	u32 i;
117362306a36Sopenharmony_ci
117462306a36Sopenharmony_ci	for (i = 0; i < eg_pi->mc_reg_table.last; i++) {
117562306a36Sopenharmony_ci		value = RREG32(eg_pi->mc_reg_table.mc_reg_address[i].s1 << 2);
117662306a36Sopenharmony_ci		WREG32(eg_pi->mc_reg_table.mc_reg_address[i].s0 << 2, value);
117762306a36Sopenharmony_ci	}
117862306a36Sopenharmony_ci}
117962306a36Sopenharmony_ci
118062306a36Sopenharmony_cistatic void cypress_force_mc_use_s0(struct radeon_device *rdev,
118162306a36Sopenharmony_ci				    struct radeon_ps *radeon_boot_state)
118262306a36Sopenharmony_ci{
118362306a36Sopenharmony_ci	struct rv7xx_ps *boot_state = rv770_get_ps(radeon_boot_state);
118462306a36Sopenharmony_ci	u32 strobe_mode;
118562306a36Sopenharmony_ci	u32 mc_seq_cg;
118662306a36Sopenharmony_ci	int i;
118762306a36Sopenharmony_ci
118862306a36Sopenharmony_ci	cypress_copy_ac_timing_from_s1_to_s0(rdev);
118962306a36Sopenharmony_ci	radeon_mc_wait_for_idle(rdev);
119062306a36Sopenharmony_ci
119162306a36Sopenharmony_ci	if ((rdev->family == CHIP_CYPRESS) ||
119262306a36Sopenharmony_ci	    (rdev->family == CHIP_HEMLOCK)) {
119362306a36Sopenharmony_ci		WREG32(MC_CONFIG_MCD, 0xf);
119462306a36Sopenharmony_ci		WREG32(MC_CG_CONFIG_MCD, 0xf);
119562306a36Sopenharmony_ci	} else {
119662306a36Sopenharmony_ci		WREG32(MC_CONFIG, 0xf);
119762306a36Sopenharmony_ci		WREG32(MC_CG_CONFIG, 0xf);
119862306a36Sopenharmony_ci	}
119962306a36Sopenharmony_ci
120062306a36Sopenharmony_ci	for (i = 0; i < rdev->num_crtc; i++)
120162306a36Sopenharmony_ci		radeon_wait_for_vblank(rdev, i);
120262306a36Sopenharmony_ci
120362306a36Sopenharmony_ci	WREG32(MC_SEQ_CG, MC_CG_SEQ_YCLK_SUSPEND);
120462306a36Sopenharmony_ci	cypress_wait_for_mc_sequencer(rdev, MC_CG_SEQ_YCLK_SUSPEND);
120562306a36Sopenharmony_ci
120662306a36Sopenharmony_ci	strobe_mode = cypress_get_strobe_mode_settings(rdev,
120762306a36Sopenharmony_ci						       boot_state->low.mclk);
120862306a36Sopenharmony_ci
120962306a36Sopenharmony_ci	mc_seq_cg = CG_SEQ_REQ(MC_CG_SEQ_DRAMCONF_S0);
121062306a36Sopenharmony_ci	mc_seq_cg |= SEQ_CG_RESP(strobe_mode);
121162306a36Sopenharmony_ci	WREG32(MC_SEQ_CG, mc_seq_cg);
121262306a36Sopenharmony_ci
121362306a36Sopenharmony_ci	for (i = 0; i < rdev->usec_timeout; i++) {
121462306a36Sopenharmony_ci		if (!(RREG32(MC_SEQ_STATUS_M) & PMG_PWRSTATE))
121562306a36Sopenharmony_ci			break;
121662306a36Sopenharmony_ci		udelay(1);
121762306a36Sopenharmony_ci	}
121862306a36Sopenharmony_ci
121962306a36Sopenharmony_ci	mc_seq_cg &= ~CG_SEQ_REQ_MASK;
122062306a36Sopenharmony_ci	mc_seq_cg |= CG_SEQ_REQ(MC_CG_SEQ_YCLK_RESUME);
122162306a36Sopenharmony_ci	WREG32(MC_SEQ_CG, mc_seq_cg);
122262306a36Sopenharmony_ci
122362306a36Sopenharmony_ci	cypress_wait_for_mc_sequencer(rdev, MC_CG_SEQ_YCLK_RESUME);
122462306a36Sopenharmony_ci}
122562306a36Sopenharmony_ci
122662306a36Sopenharmony_cistatic int cypress_populate_initial_mvdd_value(struct radeon_device *rdev,
122762306a36Sopenharmony_ci					       RV770_SMC_VOLTAGE_VALUE *voltage)
122862306a36Sopenharmony_ci{
122962306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
123062306a36Sopenharmony_ci
123162306a36Sopenharmony_ci	voltage->index = eg_pi->mvdd_high_index;
123262306a36Sopenharmony_ci	voltage->value = cpu_to_be16(MVDD_HIGH_VALUE);
123362306a36Sopenharmony_ci
123462306a36Sopenharmony_ci	return 0;
123562306a36Sopenharmony_ci}
123662306a36Sopenharmony_ci
123762306a36Sopenharmony_ciint cypress_populate_smc_initial_state(struct radeon_device *rdev,
123862306a36Sopenharmony_ci				       struct radeon_ps *radeon_initial_state,
123962306a36Sopenharmony_ci				       RV770_SMC_STATETABLE *table)
124062306a36Sopenharmony_ci{
124162306a36Sopenharmony_ci	struct rv7xx_ps *initial_state = rv770_get_ps(radeon_initial_state);
124262306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
124362306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
124462306a36Sopenharmony_ci	u32 a_t;
124562306a36Sopenharmony_ci
124662306a36Sopenharmony_ci	table->initialState.levels[0].mclk.mclk770.vMPLL_AD_FUNC_CNTL =
124762306a36Sopenharmony_ci		cpu_to_be32(pi->clk_regs.rv770.mpll_ad_func_cntl);
124862306a36Sopenharmony_ci	table->initialState.levels[0].mclk.mclk770.vMPLL_AD_FUNC_CNTL_2 =
124962306a36Sopenharmony_ci		cpu_to_be32(pi->clk_regs.rv770.mpll_ad_func_cntl_2);
125062306a36Sopenharmony_ci	table->initialState.levels[0].mclk.mclk770.vMPLL_DQ_FUNC_CNTL =
125162306a36Sopenharmony_ci		cpu_to_be32(pi->clk_regs.rv770.mpll_dq_func_cntl);
125262306a36Sopenharmony_ci	table->initialState.levels[0].mclk.mclk770.vMPLL_DQ_FUNC_CNTL_2 =
125362306a36Sopenharmony_ci		cpu_to_be32(pi->clk_regs.rv770.mpll_dq_func_cntl_2);
125462306a36Sopenharmony_ci	table->initialState.levels[0].mclk.mclk770.vMCLK_PWRMGT_CNTL =
125562306a36Sopenharmony_ci		cpu_to_be32(pi->clk_regs.rv770.mclk_pwrmgt_cntl);
125662306a36Sopenharmony_ci	table->initialState.levels[0].mclk.mclk770.vDLL_CNTL =
125762306a36Sopenharmony_ci		cpu_to_be32(pi->clk_regs.rv770.dll_cntl);
125862306a36Sopenharmony_ci
125962306a36Sopenharmony_ci	table->initialState.levels[0].mclk.mclk770.vMPLL_SS =
126062306a36Sopenharmony_ci		cpu_to_be32(pi->clk_regs.rv770.mpll_ss1);
126162306a36Sopenharmony_ci	table->initialState.levels[0].mclk.mclk770.vMPLL_SS2 =
126262306a36Sopenharmony_ci		cpu_to_be32(pi->clk_regs.rv770.mpll_ss2);
126362306a36Sopenharmony_ci
126462306a36Sopenharmony_ci	table->initialState.levels[0].mclk.mclk770.mclk_value =
126562306a36Sopenharmony_ci		cpu_to_be32(initial_state->low.mclk);
126662306a36Sopenharmony_ci
126762306a36Sopenharmony_ci	table->initialState.levels[0].sclk.vCG_SPLL_FUNC_CNTL =
126862306a36Sopenharmony_ci		cpu_to_be32(pi->clk_regs.rv770.cg_spll_func_cntl);
126962306a36Sopenharmony_ci	table->initialState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_2 =
127062306a36Sopenharmony_ci		cpu_to_be32(pi->clk_regs.rv770.cg_spll_func_cntl_2);
127162306a36Sopenharmony_ci	table->initialState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_3 =
127262306a36Sopenharmony_ci		cpu_to_be32(pi->clk_regs.rv770.cg_spll_func_cntl_3);
127362306a36Sopenharmony_ci	table->initialState.levels[0].sclk.vCG_SPLL_SPREAD_SPECTRUM =
127462306a36Sopenharmony_ci		cpu_to_be32(pi->clk_regs.rv770.cg_spll_spread_spectrum);
127562306a36Sopenharmony_ci	table->initialState.levels[0].sclk.vCG_SPLL_SPREAD_SPECTRUM_2 =
127662306a36Sopenharmony_ci		cpu_to_be32(pi->clk_regs.rv770.cg_spll_spread_spectrum_2);
127762306a36Sopenharmony_ci
127862306a36Sopenharmony_ci	table->initialState.levels[0].sclk.sclk_value =
127962306a36Sopenharmony_ci		cpu_to_be32(initial_state->low.sclk);
128062306a36Sopenharmony_ci
128162306a36Sopenharmony_ci	table->initialState.levels[0].arbValue = MC_CG_ARB_FREQ_F0;
128262306a36Sopenharmony_ci
128362306a36Sopenharmony_ci	table->initialState.levels[0].ACIndex = 0;
128462306a36Sopenharmony_ci
128562306a36Sopenharmony_ci	cypress_populate_voltage_value(rdev,
128662306a36Sopenharmony_ci				       &eg_pi->vddc_voltage_table,
128762306a36Sopenharmony_ci				       initial_state->low.vddc,
128862306a36Sopenharmony_ci				       &table->initialState.levels[0].vddc);
128962306a36Sopenharmony_ci
129062306a36Sopenharmony_ci	if (eg_pi->vddci_control)
129162306a36Sopenharmony_ci		cypress_populate_voltage_value(rdev,
129262306a36Sopenharmony_ci					       &eg_pi->vddci_voltage_table,
129362306a36Sopenharmony_ci					       initial_state->low.vddci,
129462306a36Sopenharmony_ci					       &table->initialState.levels[0].vddci);
129562306a36Sopenharmony_ci
129662306a36Sopenharmony_ci	cypress_populate_initial_mvdd_value(rdev,
129762306a36Sopenharmony_ci					    &table->initialState.levels[0].mvdd);
129862306a36Sopenharmony_ci
129962306a36Sopenharmony_ci	a_t = CG_R(0xffff) | CG_L(0);
130062306a36Sopenharmony_ci	table->initialState.levels[0].aT = cpu_to_be32(a_t);
130162306a36Sopenharmony_ci
130262306a36Sopenharmony_ci	table->initialState.levels[0].bSP = cpu_to_be32(pi->dsp);
130362306a36Sopenharmony_ci
130462306a36Sopenharmony_ci
130562306a36Sopenharmony_ci	if (pi->boot_in_gen2)
130662306a36Sopenharmony_ci		table->initialState.levels[0].gen2PCIE = 1;
130762306a36Sopenharmony_ci	else
130862306a36Sopenharmony_ci		table->initialState.levels[0].gen2PCIE = 0;
130962306a36Sopenharmony_ci	if (initial_state->low.flags & ATOM_PPLIB_R600_FLAGS_PCIEGEN2)
131062306a36Sopenharmony_ci		table->initialState.levels[0].gen2XSP = 1;
131162306a36Sopenharmony_ci	else
131262306a36Sopenharmony_ci		table->initialState.levels[0].gen2XSP = 0;
131362306a36Sopenharmony_ci
131462306a36Sopenharmony_ci	if (pi->mem_gddr5) {
131562306a36Sopenharmony_ci		table->initialState.levels[0].strobeMode =
131662306a36Sopenharmony_ci			cypress_get_strobe_mode_settings(rdev,
131762306a36Sopenharmony_ci							 initial_state->low.mclk);
131862306a36Sopenharmony_ci
131962306a36Sopenharmony_ci		if (initial_state->low.mclk > pi->mclk_edc_enable_threshold)
132062306a36Sopenharmony_ci			table->initialState.levels[0].mcFlags = SMC_MC_EDC_RD_FLAG | SMC_MC_EDC_WR_FLAG;
132162306a36Sopenharmony_ci		else
132262306a36Sopenharmony_ci			table->initialState.levels[0].mcFlags =  0;
132362306a36Sopenharmony_ci	}
132462306a36Sopenharmony_ci
132562306a36Sopenharmony_ci	table->initialState.levels[1] = table->initialState.levels[0];
132662306a36Sopenharmony_ci	table->initialState.levels[2] = table->initialState.levels[0];
132762306a36Sopenharmony_ci
132862306a36Sopenharmony_ci	table->initialState.flags |= PPSMC_SWSTATE_FLAG_DC;
132962306a36Sopenharmony_ci
133062306a36Sopenharmony_ci	return 0;
133162306a36Sopenharmony_ci}
133262306a36Sopenharmony_ci
133362306a36Sopenharmony_ciint cypress_populate_smc_acpi_state(struct radeon_device *rdev,
133462306a36Sopenharmony_ci				    RV770_SMC_STATETABLE *table)
133562306a36Sopenharmony_ci{
133662306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
133762306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
133862306a36Sopenharmony_ci	u32 mpll_ad_func_cntl =
133962306a36Sopenharmony_ci		pi->clk_regs.rv770.mpll_ad_func_cntl;
134062306a36Sopenharmony_ci	u32 mpll_ad_func_cntl_2 =
134162306a36Sopenharmony_ci		pi->clk_regs.rv770.mpll_ad_func_cntl_2;
134262306a36Sopenharmony_ci	u32 mpll_dq_func_cntl =
134362306a36Sopenharmony_ci		pi->clk_regs.rv770.mpll_dq_func_cntl;
134462306a36Sopenharmony_ci	u32 mpll_dq_func_cntl_2 =
134562306a36Sopenharmony_ci		pi->clk_regs.rv770.mpll_dq_func_cntl_2;
134662306a36Sopenharmony_ci	u32 spll_func_cntl =
134762306a36Sopenharmony_ci		pi->clk_regs.rv770.cg_spll_func_cntl;
134862306a36Sopenharmony_ci	u32 spll_func_cntl_2 =
134962306a36Sopenharmony_ci		pi->clk_regs.rv770.cg_spll_func_cntl_2;
135062306a36Sopenharmony_ci	u32 spll_func_cntl_3 =
135162306a36Sopenharmony_ci		pi->clk_regs.rv770.cg_spll_func_cntl_3;
135262306a36Sopenharmony_ci	u32 mclk_pwrmgt_cntl =
135362306a36Sopenharmony_ci		pi->clk_regs.rv770.mclk_pwrmgt_cntl;
135462306a36Sopenharmony_ci	u32 dll_cntl =
135562306a36Sopenharmony_ci		pi->clk_regs.rv770.dll_cntl;
135662306a36Sopenharmony_ci
135762306a36Sopenharmony_ci	table->ACPIState = table->initialState;
135862306a36Sopenharmony_ci
135962306a36Sopenharmony_ci	table->ACPIState.flags &= ~PPSMC_SWSTATE_FLAG_DC;
136062306a36Sopenharmony_ci
136162306a36Sopenharmony_ci	if (pi->acpi_vddc) {
136262306a36Sopenharmony_ci		cypress_populate_voltage_value(rdev,
136362306a36Sopenharmony_ci					       &eg_pi->vddc_voltage_table,
136462306a36Sopenharmony_ci					       pi->acpi_vddc,
136562306a36Sopenharmony_ci					       &table->ACPIState.levels[0].vddc);
136662306a36Sopenharmony_ci		if (pi->pcie_gen2) {
136762306a36Sopenharmony_ci			if (pi->acpi_pcie_gen2)
136862306a36Sopenharmony_ci				table->ACPIState.levels[0].gen2PCIE = 1;
136962306a36Sopenharmony_ci			else
137062306a36Sopenharmony_ci				table->ACPIState.levels[0].gen2PCIE = 0;
137162306a36Sopenharmony_ci		} else
137262306a36Sopenharmony_ci			table->ACPIState.levels[0].gen2PCIE = 0;
137362306a36Sopenharmony_ci		if (pi->acpi_pcie_gen2)
137462306a36Sopenharmony_ci			table->ACPIState.levels[0].gen2XSP = 1;
137562306a36Sopenharmony_ci		else
137662306a36Sopenharmony_ci			table->ACPIState.levels[0].gen2XSP = 0;
137762306a36Sopenharmony_ci	} else {
137862306a36Sopenharmony_ci		cypress_populate_voltage_value(rdev,
137962306a36Sopenharmony_ci					       &eg_pi->vddc_voltage_table,
138062306a36Sopenharmony_ci					       pi->min_vddc_in_table,
138162306a36Sopenharmony_ci					       &table->ACPIState.levels[0].vddc);
138262306a36Sopenharmony_ci		table->ACPIState.levels[0].gen2PCIE = 0;
138362306a36Sopenharmony_ci	}
138462306a36Sopenharmony_ci
138562306a36Sopenharmony_ci	if (eg_pi->acpi_vddci) {
138662306a36Sopenharmony_ci		if (eg_pi->vddci_control) {
138762306a36Sopenharmony_ci			cypress_populate_voltage_value(rdev,
138862306a36Sopenharmony_ci						       &eg_pi->vddci_voltage_table,
138962306a36Sopenharmony_ci						       eg_pi->acpi_vddci,
139062306a36Sopenharmony_ci						       &table->ACPIState.levels[0].vddci);
139162306a36Sopenharmony_ci		}
139262306a36Sopenharmony_ci	}
139362306a36Sopenharmony_ci
139462306a36Sopenharmony_ci	mpll_ad_func_cntl &= ~PDNB;
139562306a36Sopenharmony_ci
139662306a36Sopenharmony_ci	mpll_ad_func_cntl_2 |= BIAS_GEN_PDNB | RESET_EN;
139762306a36Sopenharmony_ci
139862306a36Sopenharmony_ci	if (pi->mem_gddr5)
139962306a36Sopenharmony_ci		mpll_dq_func_cntl &= ~PDNB;
140062306a36Sopenharmony_ci	mpll_dq_func_cntl_2 |= BIAS_GEN_PDNB | RESET_EN | BYPASS;
140162306a36Sopenharmony_ci
140262306a36Sopenharmony_ci	mclk_pwrmgt_cntl |= (MRDCKA0_RESET |
140362306a36Sopenharmony_ci			     MRDCKA1_RESET |
140462306a36Sopenharmony_ci			     MRDCKB0_RESET |
140562306a36Sopenharmony_ci			     MRDCKB1_RESET |
140662306a36Sopenharmony_ci			     MRDCKC0_RESET |
140762306a36Sopenharmony_ci			     MRDCKC1_RESET |
140862306a36Sopenharmony_ci			     MRDCKD0_RESET |
140962306a36Sopenharmony_ci			     MRDCKD1_RESET);
141062306a36Sopenharmony_ci
141162306a36Sopenharmony_ci	mclk_pwrmgt_cntl &= ~(MRDCKA0_PDNB |
141262306a36Sopenharmony_ci			      MRDCKA1_PDNB |
141362306a36Sopenharmony_ci			      MRDCKB0_PDNB |
141462306a36Sopenharmony_ci			      MRDCKB1_PDNB |
141562306a36Sopenharmony_ci			      MRDCKC0_PDNB |
141662306a36Sopenharmony_ci			      MRDCKC1_PDNB |
141762306a36Sopenharmony_ci			      MRDCKD0_PDNB |
141862306a36Sopenharmony_ci			      MRDCKD1_PDNB);
141962306a36Sopenharmony_ci
142062306a36Sopenharmony_ci	dll_cntl |= (MRDCKA0_BYPASS |
142162306a36Sopenharmony_ci		     MRDCKA1_BYPASS |
142262306a36Sopenharmony_ci		     MRDCKB0_BYPASS |
142362306a36Sopenharmony_ci		     MRDCKB1_BYPASS |
142462306a36Sopenharmony_ci		     MRDCKC0_BYPASS |
142562306a36Sopenharmony_ci		     MRDCKC1_BYPASS |
142662306a36Sopenharmony_ci		     MRDCKD0_BYPASS |
142762306a36Sopenharmony_ci		     MRDCKD1_BYPASS);
142862306a36Sopenharmony_ci
142962306a36Sopenharmony_ci	/* evergreen only */
143062306a36Sopenharmony_ci	if (rdev->family <= CHIP_HEMLOCK)
143162306a36Sopenharmony_ci		spll_func_cntl |= SPLL_RESET | SPLL_SLEEP | SPLL_BYPASS_EN;
143262306a36Sopenharmony_ci
143362306a36Sopenharmony_ci	spll_func_cntl_2 &= ~SCLK_MUX_SEL_MASK;
143462306a36Sopenharmony_ci	spll_func_cntl_2 |= SCLK_MUX_SEL(4);
143562306a36Sopenharmony_ci
143662306a36Sopenharmony_ci	table->ACPIState.levels[0].mclk.mclk770.vMPLL_AD_FUNC_CNTL =
143762306a36Sopenharmony_ci		cpu_to_be32(mpll_ad_func_cntl);
143862306a36Sopenharmony_ci	table->ACPIState.levels[0].mclk.mclk770.vMPLL_AD_FUNC_CNTL_2 =
143962306a36Sopenharmony_ci		cpu_to_be32(mpll_ad_func_cntl_2);
144062306a36Sopenharmony_ci	table->ACPIState.levels[0].mclk.mclk770.vMPLL_DQ_FUNC_CNTL =
144162306a36Sopenharmony_ci		cpu_to_be32(mpll_dq_func_cntl);
144262306a36Sopenharmony_ci	table->ACPIState.levels[0].mclk.mclk770.vMPLL_DQ_FUNC_CNTL_2 =
144362306a36Sopenharmony_ci		cpu_to_be32(mpll_dq_func_cntl_2);
144462306a36Sopenharmony_ci	table->ACPIState.levels[0].mclk.mclk770.vMCLK_PWRMGT_CNTL =
144562306a36Sopenharmony_ci		cpu_to_be32(mclk_pwrmgt_cntl);
144662306a36Sopenharmony_ci	table->ACPIState.levels[0].mclk.mclk770.vDLL_CNTL = cpu_to_be32(dll_cntl);
144762306a36Sopenharmony_ci
144862306a36Sopenharmony_ci	table->ACPIState.levels[0].mclk.mclk770.mclk_value = 0;
144962306a36Sopenharmony_ci
145062306a36Sopenharmony_ci	table->ACPIState.levels[0].sclk.vCG_SPLL_FUNC_CNTL =
145162306a36Sopenharmony_ci		cpu_to_be32(spll_func_cntl);
145262306a36Sopenharmony_ci	table->ACPIState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_2 =
145362306a36Sopenharmony_ci		cpu_to_be32(spll_func_cntl_2);
145462306a36Sopenharmony_ci	table->ACPIState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_3 =
145562306a36Sopenharmony_ci		cpu_to_be32(spll_func_cntl_3);
145662306a36Sopenharmony_ci
145762306a36Sopenharmony_ci	table->ACPIState.levels[0].sclk.sclk_value = 0;
145862306a36Sopenharmony_ci
145962306a36Sopenharmony_ci	cypress_populate_mvdd_value(rdev, 0, &table->ACPIState.levels[0].mvdd);
146062306a36Sopenharmony_ci
146162306a36Sopenharmony_ci	if (eg_pi->dynamic_ac_timing)
146262306a36Sopenharmony_ci		table->ACPIState.levels[0].ACIndex = 1;
146362306a36Sopenharmony_ci
146462306a36Sopenharmony_ci	table->ACPIState.levels[1] = table->ACPIState.levels[0];
146562306a36Sopenharmony_ci	table->ACPIState.levels[2] = table->ACPIState.levels[0];
146662306a36Sopenharmony_ci
146762306a36Sopenharmony_ci	return 0;
146862306a36Sopenharmony_ci}
146962306a36Sopenharmony_ci
147062306a36Sopenharmony_cistatic void cypress_trim_voltage_table_to_fit_state_table(struct radeon_device *rdev,
147162306a36Sopenharmony_ci							  struct atom_voltage_table *voltage_table)
147262306a36Sopenharmony_ci{
147362306a36Sopenharmony_ci	unsigned int i, diff;
147462306a36Sopenharmony_ci
147562306a36Sopenharmony_ci	if (voltage_table->count <= MAX_NO_VREG_STEPS)
147662306a36Sopenharmony_ci		return;
147762306a36Sopenharmony_ci
147862306a36Sopenharmony_ci	diff = voltage_table->count - MAX_NO_VREG_STEPS;
147962306a36Sopenharmony_ci
148062306a36Sopenharmony_ci	for (i= 0; i < MAX_NO_VREG_STEPS; i++)
148162306a36Sopenharmony_ci		voltage_table->entries[i] = voltage_table->entries[i + diff];
148262306a36Sopenharmony_ci
148362306a36Sopenharmony_ci	voltage_table->count = MAX_NO_VREG_STEPS;
148462306a36Sopenharmony_ci}
148562306a36Sopenharmony_ci
148662306a36Sopenharmony_ciint cypress_construct_voltage_tables(struct radeon_device *rdev)
148762306a36Sopenharmony_ci{
148862306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
148962306a36Sopenharmony_ci	int ret;
149062306a36Sopenharmony_ci
149162306a36Sopenharmony_ci	ret = radeon_atom_get_voltage_table(rdev, SET_VOLTAGE_TYPE_ASIC_VDDC, 0,
149262306a36Sopenharmony_ci					    &eg_pi->vddc_voltage_table);
149362306a36Sopenharmony_ci	if (ret)
149462306a36Sopenharmony_ci		return ret;
149562306a36Sopenharmony_ci
149662306a36Sopenharmony_ci	if (eg_pi->vddc_voltage_table.count > MAX_NO_VREG_STEPS)
149762306a36Sopenharmony_ci		cypress_trim_voltage_table_to_fit_state_table(rdev,
149862306a36Sopenharmony_ci							      &eg_pi->vddc_voltage_table);
149962306a36Sopenharmony_ci
150062306a36Sopenharmony_ci	if (eg_pi->vddci_control) {
150162306a36Sopenharmony_ci		ret = radeon_atom_get_voltage_table(rdev, SET_VOLTAGE_TYPE_ASIC_VDDCI, 0,
150262306a36Sopenharmony_ci						    &eg_pi->vddci_voltage_table);
150362306a36Sopenharmony_ci		if (ret)
150462306a36Sopenharmony_ci			return ret;
150562306a36Sopenharmony_ci
150662306a36Sopenharmony_ci		if (eg_pi->vddci_voltage_table.count > MAX_NO_VREG_STEPS)
150762306a36Sopenharmony_ci			cypress_trim_voltage_table_to_fit_state_table(rdev,
150862306a36Sopenharmony_ci								      &eg_pi->vddci_voltage_table);
150962306a36Sopenharmony_ci	}
151062306a36Sopenharmony_ci
151162306a36Sopenharmony_ci	return 0;
151262306a36Sopenharmony_ci}
151362306a36Sopenharmony_ci
151462306a36Sopenharmony_cistatic void cypress_populate_smc_voltage_table(struct radeon_device *rdev,
151562306a36Sopenharmony_ci					       struct atom_voltage_table *voltage_table,
151662306a36Sopenharmony_ci					       RV770_SMC_STATETABLE *table)
151762306a36Sopenharmony_ci{
151862306a36Sopenharmony_ci	unsigned int i;
151962306a36Sopenharmony_ci
152062306a36Sopenharmony_ci	for (i = 0; i < voltage_table->count; i++) {
152162306a36Sopenharmony_ci		table->highSMIO[i] = 0;
152262306a36Sopenharmony_ci		table->lowSMIO[i] |= cpu_to_be32(voltage_table->entries[i].smio_low);
152362306a36Sopenharmony_ci	}
152462306a36Sopenharmony_ci}
152562306a36Sopenharmony_ci
152662306a36Sopenharmony_ciint cypress_populate_smc_voltage_tables(struct radeon_device *rdev,
152762306a36Sopenharmony_ci					RV770_SMC_STATETABLE *table)
152862306a36Sopenharmony_ci{
152962306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
153062306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
153162306a36Sopenharmony_ci	unsigned char i;
153262306a36Sopenharmony_ci
153362306a36Sopenharmony_ci	if (eg_pi->vddc_voltage_table.count) {
153462306a36Sopenharmony_ci		cypress_populate_smc_voltage_table(rdev,
153562306a36Sopenharmony_ci						   &eg_pi->vddc_voltage_table,
153662306a36Sopenharmony_ci						   table);
153762306a36Sopenharmony_ci
153862306a36Sopenharmony_ci		table->voltageMaskTable.highMask[RV770_SMC_VOLTAGEMASK_VDDC] = 0;
153962306a36Sopenharmony_ci		table->voltageMaskTable.lowMask[RV770_SMC_VOLTAGEMASK_VDDC] =
154062306a36Sopenharmony_ci			cpu_to_be32(eg_pi->vddc_voltage_table.mask_low);
154162306a36Sopenharmony_ci
154262306a36Sopenharmony_ci		for (i = 0; i < eg_pi->vddc_voltage_table.count; i++) {
154362306a36Sopenharmony_ci			if (pi->max_vddc_in_table <=
154462306a36Sopenharmony_ci			    eg_pi->vddc_voltage_table.entries[i].value) {
154562306a36Sopenharmony_ci				table->maxVDDCIndexInPPTable = i;
154662306a36Sopenharmony_ci				break;
154762306a36Sopenharmony_ci			}
154862306a36Sopenharmony_ci		}
154962306a36Sopenharmony_ci	}
155062306a36Sopenharmony_ci
155162306a36Sopenharmony_ci	if (eg_pi->vddci_voltage_table.count) {
155262306a36Sopenharmony_ci		cypress_populate_smc_voltage_table(rdev,
155362306a36Sopenharmony_ci						   &eg_pi->vddci_voltage_table,
155462306a36Sopenharmony_ci						   table);
155562306a36Sopenharmony_ci
155662306a36Sopenharmony_ci		table->voltageMaskTable.highMask[RV770_SMC_VOLTAGEMASK_VDDCI] = 0;
155762306a36Sopenharmony_ci		table->voltageMaskTable.lowMask[RV770_SMC_VOLTAGEMASK_VDDCI] =
155862306a36Sopenharmony_ci			cpu_to_be32(eg_pi->vddci_voltage_table.mask_low);
155962306a36Sopenharmony_ci	}
156062306a36Sopenharmony_ci
156162306a36Sopenharmony_ci	return 0;
156262306a36Sopenharmony_ci}
156362306a36Sopenharmony_ci
156462306a36Sopenharmony_cistatic u32 cypress_get_mclk_split_point(struct atom_memory_info *memory_info)
156562306a36Sopenharmony_ci{
156662306a36Sopenharmony_ci	if ((memory_info->mem_type == MEM_TYPE_GDDR3) ||
156762306a36Sopenharmony_ci	    (memory_info->mem_type == MEM_TYPE_DDR3))
156862306a36Sopenharmony_ci		return 30000;
156962306a36Sopenharmony_ci
157062306a36Sopenharmony_ci	return 0;
157162306a36Sopenharmony_ci}
157262306a36Sopenharmony_ci
157362306a36Sopenharmony_ciint cypress_get_mvdd_configuration(struct radeon_device *rdev)
157462306a36Sopenharmony_ci{
157562306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
157662306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
157762306a36Sopenharmony_ci	u8 module_index;
157862306a36Sopenharmony_ci	struct atom_memory_info memory_info;
157962306a36Sopenharmony_ci	u32 tmp = RREG32(GENERAL_PWRMGT);
158062306a36Sopenharmony_ci
158162306a36Sopenharmony_ci	if (!(tmp & BACKBIAS_PAD_EN)) {
158262306a36Sopenharmony_ci		eg_pi->mvdd_high_index = 0;
158362306a36Sopenharmony_ci		eg_pi->mvdd_low_index = 1;
158462306a36Sopenharmony_ci		pi->mvdd_control = false;
158562306a36Sopenharmony_ci		return 0;
158662306a36Sopenharmony_ci	}
158762306a36Sopenharmony_ci
158862306a36Sopenharmony_ci	if (tmp & BACKBIAS_VALUE)
158962306a36Sopenharmony_ci		eg_pi->mvdd_high_index = 1;
159062306a36Sopenharmony_ci	else
159162306a36Sopenharmony_ci		eg_pi->mvdd_high_index = 0;
159262306a36Sopenharmony_ci
159362306a36Sopenharmony_ci	eg_pi->mvdd_low_index =
159462306a36Sopenharmony_ci		(eg_pi->mvdd_high_index == 0) ? 1 : 0;
159562306a36Sopenharmony_ci
159662306a36Sopenharmony_ci	module_index = rv770_get_memory_module_index(rdev);
159762306a36Sopenharmony_ci
159862306a36Sopenharmony_ci	if (radeon_atom_get_memory_info(rdev, module_index, &memory_info)) {
159962306a36Sopenharmony_ci		pi->mvdd_control = false;
160062306a36Sopenharmony_ci		return 0;
160162306a36Sopenharmony_ci	}
160262306a36Sopenharmony_ci
160362306a36Sopenharmony_ci	pi->mvdd_split_frequency =
160462306a36Sopenharmony_ci		cypress_get_mclk_split_point(&memory_info);
160562306a36Sopenharmony_ci
160662306a36Sopenharmony_ci	if (pi->mvdd_split_frequency == 0) {
160762306a36Sopenharmony_ci		pi->mvdd_control = false;
160862306a36Sopenharmony_ci		return 0;
160962306a36Sopenharmony_ci	}
161062306a36Sopenharmony_ci
161162306a36Sopenharmony_ci	return 0;
161262306a36Sopenharmony_ci}
161362306a36Sopenharmony_ci
161462306a36Sopenharmony_cistatic int cypress_init_smc_table(struct radeon_device *rdev,
161562306a36Sopenharmony_ci				  struct radeon_ps *radeon_boot_state)
161662306a36Sopenharmony_ci{
161762306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
161862306a36Sopenharmony_ci	RV770_SMC_STATETABLE *table = &pi->smc_statetable;
161962306a36Sopenharmony_ci	int ret;
162062306a36Sopenharmony_ci
162162306a36Sopenharmony_ci	memset(table, 0, sizeof(RV770_SMC_STATETABLE));
162262306a36Sopenharmony_ci
162362306a36Sopenharmony_ci	cypress_populate_smc_voltage_tables(rdev, table);
162462306a36Sopenharmony_ci
162562306a36Sopenharmony_ci	switch (rdev->pm.int_thermal_type) {
162662306a36Sopenharmony_ci	case THERMAL_TYPE_EVERGREEN:
162762306a36Sopenharmony_ci	case THERMAL_TYPE_EMC2103_WITH_INTERNAL:
162862306a36Sopenharmony_ci		table->thermalProtectType = PPSMC_THERMAL_PROTECT_TYPE_INTERNAL;
162962306a36Sopenharmony_ci		break;
163062306a36Sopenharmony_ci	case THERMAL_TYPE_NONE:
163162306a36Sopenharmony_ci		table->thermalProtectType = PPSMC_THERMAL_PROTECT_TYPE_NONE;
163262306a36Sopenharmony_ci		break;
163362306a36Sopenharmony_ci	default:
163462306a36Sopenharmony_ci		table->thermalProtectType = PPSMC_THERMAL_PROTECT_TYPE_EXTERNAL;
163562306a36Sopenharmony_ci		break;
163662306a36Sopenharmony_ci	}
163762306a36Sopenharmony_ci
163862306a36Sopenharmony_ci	if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_HARDWAREDC)
163962306a36Sopenharmony_ci		table->systemFlags |= PPSMC_SYSTEMFLAG_GPIO_DC;
164062306a36Sopenharmony_ci
164162306a36Sopenharmony_ci	if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_REGULATOR_HOT)
164262306a36Sopenharmony_ci		table->systemFlags |= PPSMC_SYSTEMFLAG_REGULATOR_HOT;
164362306a36Sopenharmony_ci
164462306a36Sopenharmony_ci	if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_STEPVDDC)
164562306a36Sopenharmony_ci		table->systemFlags |= PPSMC_SYSTEMFLAG_STEPVDDC;
164662306a36Sopenharmony_ci
164762306a36Sopenharmony_ci	if (pi->mem_gddr5)
164862306a36Sopenharmony_ci		table->systemFlags |= PPSMC_SYSTEMFLAG_GDDR5;
164962306a36Sopenharmony_ci
165062306a36Sopenharmony_ci	ret = cypress_populate_smc_initial_state(rdev, radeon_boot_state, table);
165162306a36Sopenharmony_ci	if (ret)
165262306a36Sopenharmony_ci		return ret;
165362306a36Sopenharmony_ci
165462306a36Sopenharmony_ci	ret = cypress_populate_smc_acpi_state(rdev, table);
165562306a36Sopenharmony_ci	if (ret)
165662306a36Sopenharmony_ci		return ret;
165762306a36Sopenharmony_ci
165862306a36Sopenharmony_ci	table->driverState = table->initialState;
165962306a36Sopenharmony_ci
166062306a36Sopenharmony_ci	return rv770_copy_bytes_to_smc(rdev,
166162306a36Sopenharmony_ci				       pi->state_table_start,
166262306a36Sopenharmony_ci				       (u8 *)table, sizeof(RV770_SMC_STATETABLE),
166362306a36Sopenharmony_ci				       pi->sram_end);
166462306a36Sopenharmony_ci}
166562306a36Sopenharmony_ci
166662306a36Sopenharmony_ciint cypress_populate_mc_reg_table(struct radeon_device *rdev,
166762306a36Sopenharmony_ci				  struct radeon_ps *radeon_boot_state)
166862306a36Sopenharmony_ci{
166962306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
167062306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
167162306a36Sopenharmony_ci	struct rv7xx_ps *boot_state = rv770_get_ps(radeon_boot_state);
167262306a36Sopenharmony_ci	SMC_Evergreen_MCRegisters mc_reg_table = { 0 };
167362306a36Sopenharmony_ci
167462306a36Sopenharmony_ci	rv770_write_smc_soft_register(rdev,
167562306a36Sopenharmony_ci				      RV770_SMC_SOFT_REGISTER_seq_index, 1);
167662306a36Sopenharmony_ci
167762306a36Sopenharmony_ci	cypress_populate_mc_reg_addresses(rdev, &mc_reg_table);
167862306a36Sopenharmony_ci
167962306a36Sopenharmony_ci	cypress_convert_mc_reg_table_entry_to_smc(rdev,
168062306a36Sopenharmony_ci						  &boot_state->low,
168162306a36Sopenharmony_ci						  &mc_reg_table.data[0]);
168262306a36Sopenharmony_ci
168362306a36Sopenharmony_ci	cypress_convert_mc_registers(&eg_pi->mc_reg_table.mc_reg_table_entry[0],
168462306a36Sopenharmony_ci				     &mc_reg_table.data[1], eg_pi->mc_reg_table.last,
168562306a36Sopenharmony_ci				     eg_pi->mc_reg_table.valid_flag);
168662306a36Sopenharmony_ci
168762306a36Sopenharmony_ci	cypress_convert_mc_reg_table_to_smc(rdev, radeon_boot_state, &mc_reg_table);
168862306a36Sopenharmony_ci
168962306a36Sopenharmony_ci	return rv770_copy_bytes_to_smc(rdev, eg_pi->mc_reg_table_start,
169062306a36Sopenharmony_ci				       (u8 *)&mc_reg_table, sizeof(SMC_Evergreen_MCRegisters),
169162306a36Sopenharmony_ci				       pi->sram_end);
169262306a36Sopenharmony_ci}
169362306a36Sopenharmony_ci
169462306a36Sopenharmony_ciint cypress_get_table_locations(struct radeon_device *rdev)
169562306a36Sopenharmony_ci{
169662306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
169762306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
169862306a36Sopenharmony_ci	u32 tmp;
169962306a36Sopenharmony_ci	int ret;
170062306a36Sopenharmony_ci
170162306a36Sopenharmony_ci	ret = rv770_read_smc_sram_dword(rdev,
170262306a36Sopenharmony_ci					EVERGREEN_SMC_FIRMWARE_HEADER_LOCATION +
170362306a36Sopenharmony_ci					EVERGREEN_SMC_FIRMWARE_HEADER_stateTable,
170462306a36Sopenharmony_ci					&tmp, pi->sram_end);
170562306a36Sopenharmony_ci	if (ret)
170662306a36Sopenharmony_ci		return ret;
170762306a36Sopenharmony_ci
170862306a36Sopenharmony_ci	pi->state_table_start = (u16)tmp;
170962306a36Sopenharmony_ci
171062306a36Sopenharmony_ci	ret = rv770_read_smc_sram_dword(rdev,
171162306a36Sopenharmony_ci					EVERGREEN_SMC_FIRMWARE_HEADER_LOCATION +
171262306a36Sopenharmony_ci					EVERGREEN_SMC_FIRMWARE_HEADER_softRegisters,
171362306a36Sopenharmony_ci					&tmp, pi->sram_end);
171462306a36Sopenharmony_ci	if (ret)
171562306a36Sopenharmony_ci		return ret;
171662306a36Sopenharmony_ci
171762306a36Sopenharmony_ci	pi->soft_regs_start = (u16)tmp;
171862306a36Sopenharmony_ci
171962306a36Sopenharmony_ci	ret = rv770_read_smc_sram_dword(rdev,
172062306a36Sopenharmony_ci					EVERGREEN_SMC_FIRMWARE_HEADER_LOCATION +
172162306a36Sopenharmony_ci					EVERGREEN_SMC_FIRMWARE_HEADER_mcRegisterTable,
172262306a36Sopenharmony_ci					&tmp, pi->sram_end);
172362306a36Sopenharmony_ci	if (ret)
172462306a36Sopenharmony_ci		return ret;
172562306a36Sopenharmony_ci
172662306a36Sopenharmony_ci	eg_pi->mc_reg_table_start = (u16)tmp;
172762306a36Sopenharmony_ci
172862306a36Sopenharmony_ci	return 0;
172962306a36Sopenharmony_ci}
173062306a36Sopenharmony_ci
173162306a36Sopenharmony_civoid cypress_enable_display_gap(struct radeon_device *rdev)
173262306a36Sopenharmony_ci{
173362306a36Sopenharmony_ci	u32 tmp = RREG32(CG_DISPLAY_GAP_CNTL);
173462306a36Sopenharmony_ci
173562306a36Sopenharmony_ci	tmp &= ~(DISP1_GAP_MASK | DISP2_GAP_MASK);
173662306a36Sopenharmony_ci	tmp |= (DISP1_GAP(R600_PM_DISPLAY_GAP_IGNORE) |
173762306a36Sopenharmony_ci		DISP2_GAP(R600_PM_DISPLAY_GAP_IGNORE));
173862306a36Sopenharmony_ci
173962306a36Sopenharmony_ci	tmp &= ~(DISP1_GAP_MCHG_MASK | DISP2_GAP_MCHG_MASK);
174062306a36Sopenharmony_ci	tmp |= (DISP1_GAP_MCHG(R600_PM_DISPLAY_GAP_VBLANK) |
174162306a36Sopenharmony_ci		DISP2_GAP_MCHG(R600_PM_DISPLAY_GAP_IGNORE));
174262306a36Sopenharmony_ci	WREG32(CG_DISPLAY_GAP_CNTL, tmp);
174362306a36Sopenharmony_ci}
174462306a36Sopenharmony_ci
174562306a36Sopenharmony_cistatic void cypress_program_display_gap(struct radeon_device *rdev)
174662306a36Sopenharmony_ci{
174762306a36Sopenharmony_ci	u32 tmp, pipe;
174862306a36Sopenharmony_ci	int i;
174962306a36Sopenharmony_ci
175062306a36Sopenharmony_ci	tmp = RREG32(CG_DISPLAY_GAP_CNTL) & ~(DISP1_GAP_MASK | DISP2_GAP_MASK);
175162306a36Sopenharmony_ci	if (rdev->pm.dpm.new_active_crtc_count > 0)
175262306a36Sopenharmony_ci		tmp |= DISP1_GAP(R600_PM_DISPLAY_GAP_VBLANK_OR_WM);
175362306a36Sopenharmony_ci	else
175462306a36Sopenharmony_ci		tmp |= DISP1_GAP(R600_PM_DISPLAY_GAP_IGNORE);
175562306a36Sopenharmony_ci
175662306a36Sopenharmony_ci	if (rdev->pm.dpm.new_active_crtc_count > 1)
175762306a36Sopenharmony_ci		tmp |= DISP2_GAP(R600_PM_DISPLAY_GAP_VBLANK_OR_WM);
175862306a36Sopenharmony_ci	else
175962306a36Sopenharmony_ci		tmp |= DISP2_GAP(R600_PM_DISPLAY_GAP_IGNORE);
176062306a36Sopenharmony_ci
176162306a36Sopenharmony_ci	WREG32(CG_DISPLAY_GAP_CNTL, tmp);
176262306a36Sopenharmony_ci
176362306a36Sopenharmony_ci	tmp = RREG32(DCCG_DISP_SLOW_SELECT_REG);
176462306a36Sopenharmony_ci	pipe = (tmp & DCCG_DISP1_SLOW_SELECT_MASK) >> DCCG_DISP1_SLOW_SELECT_SHIFT;
176562306a36Sopenharmony_ci
176662306a36Sopenharmony_ci	if ((rdev->pm.dpm.new_active_crtc_count > 0) &&
176762306a36Sopenharmony_ci	    (!(rdev->pm.dpm.new_active_crtcs & (1 << pipe)))) {
176862306a36Sopenharmony_ci		/* find the first active crtc */
176962306a36Sopenharmony_ci		for (i = 0; i < rdev->num_crtc; i++) {
177062306a36Sopenharmony_ci			if (rdev->pm.dpm.new_active_crtcs & (1 << i))
177162306a36Sopenharmony_ci				break;
177262306a36Sopenharmony_ci		}
177362306a36Sopenharmony_ci		if (i == rdev->num_crtc)
177462306a36Sopenharmony_ci			pipe = 0;
177562306a36Sopenharmony_ci		else
177662306a36Sopenharmony_ci			pipe = i;
177762306a36Sopenharmony_ci
177862306a36Sopenharmony_ci		tmp &= ~DCCG_DISP1_SLOW_SELECT_MASK;
177962306a36Sopenharmony_ci		tmp |= DCCG_DISP1_SLOW_SELECT(pipe);
178062306a36Sopenharmony_ci		WREG32(DCCG_DISP_SLOW_SELECT_REG, tmp);
178162306a36Sopenharmony_ci	}
178262306a36Sopenharmony_ci
178362306a36Sopenharmony_ci	cypress_notify_smc_display_change(rdev, rdev->pm.dpm.new_active_crtc_count > 0);
178462306a36Sopenharmony_ci}
178562306a36Sopenharmony_ci
178662306a36Sopenharmony_civoid cypress_dpm_setup_asic(struct radeon_device *rdev)
178762306a36Sopenharmony_ci{
178862306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
178962306a36Sopenharmony_ci
179062306a36Sopenharmony_ci	rv740_read_clock_registers(rdev);
179162306a36Sopenharmony_ci	rv770_read_voltage_smio_registers(rdev);
179262306a36Sopenharmony_ci	rv770_get_max_vddc(rdev);
179362306a36Sopenharmony_ci	rv770_get_memory_type(rdev);
179462306a36Sopenharmony_ci
179562306a36Sopenharmony_ci	if (eg_pi->pcie_performance_request)
179662306a36Sopenharmony_ci		eg_pi->pcie_performance_request_registered = false;
179762306a36Sopenharmony_ci
179862306a36Sopenharmony_ci	if (eg_pi->pcie_performance_request)
179962306a36Sopenharmony_ci		cypress_advertise_gen2_capability(rdev);
180062306a36Sopenharmony_ci
180162306a36Sopenharmony_ci	rv770_get_pcie_gen2_status(rdev);
180262306a36Sopenharmony_ci
180362306a36Sopenharmony_ci	rv770_enable_acpi_pm(rdev);
180462306a36Sopenharmony_ci}
180562306a36Sopenharmony_ci
180662306a36Sopenharmony_ciint cypress_dpm_enable(struct radeon_device *rdev)
180762306a36Sopenharmony_ci{
180862306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
180962306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
181062306a36Sopenharmony_ci	struct radeon_ps *boot_ps = rdev->pm.dpm.boot_ps;
181162306a36Sopenharmony_ci	int ret;
181262306a36Sopenharmony_ci
181362306a36Sopenharmony_ci	if (pi->gfx_clock_gating)
181462306a36Sopenharmony_ci		rv770_restore_cgcg(rdev);
181562306a36Sopenharmony_ci
181662306a36Sopenharmony_ci	if (rv770_dpm_enabled(rdev))
181762306a36Sopenharmony_ci		return -EINVAL;
181862306a36Sopenharmony_ci
181962306a36Sopenharmony_ci	if (pi->voltage_control) {
182062306a36Sopenharmony_ci		rv770_enable_voltage_control(rdev, true);
182162306a36Sopenharmony_ci		ret = cypress_construct_voltage_tables(rdev);
182262306a36Sopenharmony_ci		if (ret) {
182362306a36Sopenharmony_ci			DRM_ERROR("cypress_construct_voltage_tables failed\n");
182462306a36Sopenharmony_ci			return ret;
182562306a36Sopenharmony_ci		}
182662306a36Sopenharmony_ci	}
182762306a36Sopenharmony_ci
182862306a36Sopenharmony_ci	if (pi->mvdd_control) {
182962306a36Sopenharmony_ci		ret = cypress_get_mvdd_configuration(rdev);
183062306a36Sopenharmony_ci		if (ret) {
183162306a36Sopenharmony_ci			DRM_ERROR("cypress_get_mvdd_configuration failed\n");
183262306a36Sopenharmony_ci			return ret;
183362306a36Sopenharmony_ci		}
183462306a36Sopenharmony_ci	}
183562306a36Sopenharmony_ci
183662306a36Sopenharmony_ci	if (eg_pi->dynamic_ac_timing) {
183762306a36Sopenharmony_ci		cypress_set_mc_reg_address_table(rdev);
183862306a36Sopenharmony_ci		cypress_force_mc_use_s0(rdev, boot_ps);
183962306a36Sopenharmony_ci		ret = cypress_initialize_mc_reg_table(rdev);
184062306a36Sopenharmony_ci		if (ret)
184162306a36Sopenharmony_ci			eg_pi->dynamic_ac_timing = false;
184262306a36Sopenharmony_ci		cypress_force_mc_use_s1(rdev, boot_ps);
184362306a36Sopenharmony_ci	}
184462306a36Sopenharmony_ci
184562306a36Sopenharmony_ci	if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_BACKBIAS)
184662306a36Sopenharmony_ci		rv770_enable_backbias(rdev, true);
184762306a36Sopenharmony_ci
184862306a36Sopenharmony_ci	if (pi->dynamic_ss)
184962306a36Sopenharmony_ci		cypress_enable_spread_spectrum(rdev, true);
185062306a36Sopenharmony_ci
185162306a36Sopenharmony_ci	if (pi->thermal_protection)
185262306a36Sopenharmony_ci		rv770_enable_thermal_protection(rdev, true);
185362306a36Sopenharmony_ci
185462306a36Sopenharmony_ci	rv770_setup_bsp(rdev);
185562306a36Sopenharmony_ci	rv770_program_git(rdev);
185662306a36Sopenharmony_ci	rv770_program_tp(rdev);
185762306a36Sopenharmony_ci	rv770_program_tpp(rdev);
185862306a36Sopenharmony_ci	rv770_program_sstp(rdev);
185962306a36Sopenharmony_ci	rv770_program_engine_speed_parameters(rdev);
186062306a36Sopenharmony_ci	cypress_enable_display_gap(rdev);
186162306a36Sopenharmony_ci	rv770_program_vc(rdev);
186262306a36Sopenharmony_ci
186362306a36Sopenharmony_ci	if (pi->dynamic_pcie_gen2)
186462306a36Sopenharmony_ci		cypress_enable_dynamic_pcie_gen2(rdev, true);
186562306a36Sopenharmony_ci
186662306a36Sopenharmony_ci	ret = rv770_upload_firmware(rdev);
186762306a36Sopenharmony_ci	if (ret) {
186862306a36Sopenharmony_ci		DRM_ERROR("rv770_upload_firmware failed\n");
186962306a36Sopenharmony_ci		return ret;
187062306a36Sopenharmony_ci	}
187162306a36Sopenharmony_ci
187262306a36Sopenharmony_ci	ret = cypress_get_table_locations(rdev);
187362306a36Sopenharmony_ci	if (ret) {
187462306a36Sopenharmony_ci		DRM_ERROR("cypress_get_table_locations failed\n");
187562306a36Sopenharmony_ci		return ret;
187662306a36Sopenharmony_ci	}
187762306a36Sopenharmony_ci	ret = cypress_init_smc_table(rdev, boot_ps);
187862306a36Sopenharmony_ci	if (ret) {
187962306a36Sopenharmony_ci		DRM_ERROR("cypress_init_smc_table failed\n");
188062306a36Sopenharmony_ci		return ret;
188162306a36Sopenharmony_ci	}
188262306a36Sopenharmony_ci	if (eg_pi->dynamic_ac_timing) {
188362306a36Sopenharmony_ci		ret = cypress_populate_mc_reg_table(rdev, boot_ps);
188462306a36Sopenharmony_ci		if (ret) {
188562306a36Sopenharmony_ci			DRM_ERROR("cypress_populate_mc_reg_table failed\n");
188662306a36Sopenharmony_ci			return ret;
188762306a36Sopenharmony_ci		}
188862306a36Sopenharmony_ci	}
188962306a36Sopenharmony_ci
189062306a36Sopenharmony_ci	cypress_program_response_times(rdev);
189162306a36Sopenharmony_ci
189262306a36Sopenharmony_ci	r7xx_start_smc(rdev);
189362306a36Sopenharmony_ci
189462306a36Sopenharmony_ci	ret = cypress_notify_smc_display_change(rdev, false);
189562306a36Sopenharmony_ci	if (ret) {
189662306a36Sopenharmony_ci		DRM_ERROR("cypress_notify_smc_display_change failed\n");
189762306a36Sopenharmony_ci		return ret;
189862306a36Sopenharmony_ci	}
189962306a36Sopenharmony_ci	cypress_enable_sclk_control(rdev, true);
190062306a36Sopenharmony_ci
190162306a36Sopenharmony_ci	if (eg_pi->memory_transition)
190262306a36Sopenharmony_ci		cypress_enable_mclk_control(rdev, true);
190362306a36Sopenharmony_ci
190462306a36Sopenharmony_ci	cypress_start_dpm(rdev);
190562306a36Sopenharmony_ci
190662306a36Sopenharmony_ci	if (pi->gfx_clock_gating)
190762306a36Sopenharmony_ci		cypress_gfx_clock_gating_enable(rdev, true);
190862306a36Sopenharmony_ci
190962306a36Sopenharmony_ci	if (pi->mg_clock_gating)
191062306a36Sopenharmony_ci		cypress_mg_clock_gating_enable(rdev, true);
191162306a36Sopenharmony_ci
191262306a36Sopenharmony_ci	rv770_enable_auto_throttle_source(rdev, RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL, true);
191362306a36Sopenharmony_ci
191462306a36Sopenharmony_ci	return 0;
191562306a36Sopenharmony_ci}
191662306a36Sopenharmony_ci
191762306a36Sopenharmony_civoid cypress_dpm_disable(struct radeon_device *rdev)
191862306a36Sopenharmony_ci{
191962306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
192062306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
192162306a36Sopenharmony_ci	struct radeon_ps *boot_ps = rdev->pm.dpm.boot_ps;
192262306a36Sopenharmony_ci
192362306a36Sopenharmony_ci	if (!rv770_dpm_enabled(rdev))
192462306a36Sopenharmony_ci		return;
192562306a36Sopenharmony_ci
192662306a36Sopenharmony_ci	rv770_clear_vc(rdev);
192762306a36Sopenharmony_ci
192862306a36Sopenharmony_ci	if (pi->thermal_protection)
192962306a36Sopenharmony_ci		rv770_enable_thermal_protection(rdev, false);
193062306a36Sopenharmony_ci
193162306a36Sopenharmony_ci	if (pi->dynamic_pcie_gen2)
193262306a36Sopenharmony_ci		cypress_enable_dynamic_pcie_gen2(rdev, false);
193362306a36Sopenharmony_ci
193462306a36Sopenharmony_ci	if (rdev->irq.installed &&
193562306a36Sopenharmony_ci	    r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
193662306a36Sopenharmony_ci		rdev->irq.dpm_thermal = false;
193762306a36Sopenharmony_ci		radeon_irq_set(rdev);
193862306a36Sopenharmony_ci	}
193962306a36Sopenharmony_ci
194062306a36Sopenharmony_ci	if (pi->gfx_clock_gating)
194162306a36Sopenharmony_ci		cypress_gfx_clock_gating_enable(rdev, false);
194262306a36Sopenharmony_ci
194362306a36Sopenharmony_ci	if (pi->mg_clock_gating)
194462306a36Sopenharmony_ci		cypress_mg_clock_gating_enable(rdev, false);
194562306a36Sopenharmony_ci
194662306a36Sopenharmony_ci	rv770_stop_dpm(rdev);
194762306a36Sopenharmony_ci	r7xx_stop_smc(rdev);
194862306a36Sopenharmony_ci
194962306a36Sopenharmony_ci	cypress_enable_spread_spectrum(rdev, false);
195062306a36Sopenharmony_ci
195162306a36Sopenharmony_ci	if (eg_pi->dynamic_ac_timing)
195262306a36Sopenharmony_ci		cypress_force_mc_use_s1(rdev, boot_ps);
195362306a36Sopenharmony_ci
195462306a36Sopenharmony_ci	rv770_reset_smio_status(rdev);
195562306a36Sopenharmony_ci}
195662306a36Sopenharmony_ci
195762306a36Sopenharmony_ciint cypress_dpm_set_power_state(struct radeon_device *rdev)
195862306a36Sopenharmony_ci{
195962306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
196062306a36Sopenharmony_ci	struct radeon_ps *new_ps = rdev->pm.dpm.requested_ps;
196162306a36Sopenharmony_ci	struct radeon_ps *old_ps = rdev->pm.dpm.current_ps;
196262306a36Sopenharmony_ci	int ret;
196362306a36Sopenharmony_ci
196462306a36Sopenharmony_ci	ret = rv770_restrict_performance_levels_before_switch(rdev);
196562306a36Sopenharmony_ci	if (ret) {
196662306a36Sopenharmony_ci		DRM_ERROR("rv770_restrict_performance_levels_before_switch failed\n");
196762306a36Sopenharmony_ci		return ret;
196862306a36Sopenharmony_ci	}
196962306a36Sopenharmony_ci	if (eg_pi->pcie_performance_request)
197062306a36Sopenharmony_ci		cypress_notify_link_speed_change_before_state_change(rdev, new_ps, old_ps);
197162306a36Sopenharmony_ci
197262306a36Sopenharmony_ci	rv770_set_uvd_clock_before_set_eng_clock(rdev, new_ps, old_ps);
197362306a36Sopenharmony_ci	ret = rv770_halt_smc(rdev);
197462306a36Sopenharmony_ci	if (ret) {
197562306a36Sopenharmony_ci		DRM_ERROR("rv770_halt_smc failed\n");
197662306a36Sopenharmony_ci		return ret;
197762306a36Sopenharmony_ci	}
197862306a36Sopenharmony_ci	ret = cypress_upload_sw_state(rdev, new_ps);
197962306a36Sopenharmony_ci	if (ret) {
198062306a36Sopenharmony_ci		DRM_ERROR("cypress_upload_sw_state failed\n");
198162306a36Sopenharmony_ci		return ret;
198262306a36Sopenharmony_ci	}
198362306a36Sopenharmony_ci	if (eg_pi->dynamic_ac_timing) {
198462306a36Sopenharmony_ci		ret = cypress_upload_mc_reg_table(rdev, new_ps);
198562306a36Sopenharmony_ci		if (ret) {
198662306a36Sopenharmony_ci			DRM_ERROR("cypress_upload_mc_reg_table failed\n");
198762306a36Sopenharmony_ci			return ret;
198862306a36Sopenharmony_ci		}
198962306a36Sopenharmony_ci	}
199062306a36Sopenharmony_ci
199162306a36Sopenharmony_ci	cypress_program_memory_timing_parameters(rdev, new_ps);
199262306a36Sopenharmony_ci
199362306a36Sopenharmony_ci	ret = rv770_resume_smc(rdev);
199462306a36Sopenharmony_ci	if (ret) {
199562306a36Sopenharmony_ci		DRM_ERROR("rv770_resume_smc failed\n");
199662306a36Sopenharmony_ci		return ret;
199762306a36Sopenharmony_ci	}
199862306a36Sopenharmony_ci	ret = rv770_set_sw_state(rdev);
199962306a36Sopenharmony_ci	if (ret) {
200062306a36Sopenharmony_ci		DRM_ERROR("rv770_set_sw_state failed\n");
200162306a36Sopenharmony_ci		return ret;
200262306a36Sopenharmony_ci	}
200362306a36Sopenharmony_ci	rv770_set_uvd_clock_after_set_eng_clock(rdev, new_ps, old_ps);
200462306a36Sopenharmony_ci
200562306a36Sopenharmony_ci	if (eg_pi->pcie_performance_request)
200662306a36Sopenharmony_ci		cypress_notify_link_speed_change_after_state_change(rdev, new_ps, old_ps);
200762306a36Sopenharmony_ci
200862306a36Sopenharmony_ci	return 0;
200962306a36Sopenharmony_ci}
201062306a36Sopenharmony_ci
201162306a36Sopenharmony_ci#if 0
201262306a36Sopenharmony_civoid cypress_dpm_reset_asic(struct radeon_device *rdev)
201362306a36Sopenharmony_ci{
201462306a36Sopenharmony_ci	rv770_restrict_performance_levels_before_switch(rdev);
201562306a36Sopenharmony_ci	rv770_set_boot_state(rdev);
201662306a36Sopenharmony_ci}
201762306a36Sopenharmony_ci#endif
201862306a36Sopenharmony_ci
201962306a36Sopenharmony_civoid cypress_dpm_display_configuration_changed(struct radeon_device *rdev)
202062306a36Sopenharmony_ci{
202162306a36Sopenharmony_ci	cypress_program_display_gap(rdev);
202262306a36Sopenharmony_ci}
202362306a36Sopenharmony_ci
202462306a36Sopenharmony_ciint cypress_dpm_init(struct radeon_device *rdev)
202562306a36Sopenharmony_ci{
202662306a36Sopenharmony_ci	struct rv7xx_power_info *pi;
202762306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi;
202862306a36Sopenharmony_ci	struct atom_clock_dividers dividers;
202962306a36Sopenharmony_ci	int ret;
203062306a36Sopenharmony_ci
203162306a36Sopenharmony_ci	eg_pi = kzalloc(sizeof(struct evergreen_power_info), GFP_KERNEL);
203262306a36Sopenharmony_ci	if (eg_pi == NULL)
203362306a36Sopenharmony_ci		return -ENOMEM;
203462306a36Sopenharmony_ci	rdev->pm.dpm.priv = eg_pi;
203562306a36Sopenharmony_ci	pi = &eg_pi->rv7xx;
203662306a36Sopenharmony_ci
203762306a36Sopenharmony_ci	rv770_get_max_vddc(rdev);
203862306a36Sopenharmony_ci
203962306a36Sopenharmony_ci	eg_pi->ulv.supported = false;
204062306a36Sopenharmony_ci	pi->acpi_vddc = 0;
204162306a36Sopenharmony_ci	eg_pi->acpi_vddci = 0;
204262306a36Sopenharmony_ci	pi->min_vddc_in_table = 0;
204362306a36Sopenharmony_ci	pi->max_vddc_in_table = 0;
204462306a36Sopenharmony_ci
204562306a36Sopenharmony_ci	ret = r600_get_platform_caps(rdev);
204662306a36Sopenharmony_ci	if (ret)
204762306a36Sopenharmony_ci		return ret;
204862306a36Sopenharmony_ci
204962306a36Sopenharmony_ci	ret = rv7xx_parse_power_table(rdev);
205062306a36Sopenharmony_ci	if (ret)
205162306a36Sopenharmony_ci		return ret;
205262306a36Sopenharmony_ci
205362306a36Sopenharmony_ci	if (rdev->pm.dpm.voltage_response_time == 0)
205462306a36Sopenharmony_ci		rdev->pm.dpm.voltage_response_time = R600_VOLTAGERESPONSETIME_DFLT;
205562306a36Sopenharmony_ci	if (rdev->pm.dpm.backbias_response_time == 0)
205662306a36Sopenharmony_ci		rdev->pm.dpm.backbias_response_time = R600_BACKBIASRESPONSETIME_DFLT;
205762306a36Sopenharmony_ci
205862306a36Sopenharmony_ci	ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
205962306a36Sopenharmony_ci					     0, false, &dividers);
206062306a36Sopenharmony_ci	if (ret)
206162306a36Sopenharmony_ci		pi->ref_div = dividers.ref_div + 1;
206262306a36Sopenharmony_ci	else
206362306a36Sopenharmony_ci		pi->ref_div = R600_REFERENCEDIVIDER_DFLT;
206462306a36Sopenharmony_ci
206562306a36Sopenharmony_ci	pi->mclk_strobe_mode_threshold = 40000;
206662306a36Sopenharmony_ci	pi->mclk_edc_enable_threshold = 40000;
206762306a36Sopenharmony_ci	eg_pi->mclk_edc_wr_enable_threshold = 40000;
206862306a36Sopenharmony_ci
206962306a36Sopenharmony_ci	pi->rlp = RV770_RLP_DFLT;
207062306a36Sopenharmony_ci	pi->rmp = RV770_RMP_DFLT;
207162306a36Sopenharmony_ci	pi->lhp = RV770_LHP_DFLT;
207262306a36Sopenharmony_ci	pi->lmp = RV770_LMP_DFLT;
207362306a36Sopenharmony_ci
207462306a36Sopenharmony_ci	pi->voltage_control =
207562306a36Sopenharmony_ci		radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDC, 0);
207662306a36Sopenharmony_ci
207762306a36Sopenharmony_ci	pi->mvdd_control =
207862306a36Sopenharmony_ci		radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_MVDDC, 0);
207962306a36Sopenharmony_ci
208062306a36Sopenharmony_ci	eg_pi->vddci_control =
208162306a36Sopenharmony_ci		radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDCI, 0);
208262306a36Sopenharmony_ci
208362306a36Sopenharmony_ci	rv770_get_engine_memory_ss(rdev);
208462306a36Sopenharmony_ci
208562306a36Sopenharmony_ci	pi->asi = RV770_ASI_DFLT;
208662306a36Sopenharmony_ci	pi->pasi = CYPRESS_HASI_DFLT;
208762306a36Sopenharmony_ci	pi->vrc = CYPRESS_VRC_DFLT;
208862306a36Sopenharmony_ci
208962306a36Sopenharmony_ci	pi->power_gating = false;
209062306a36Sopenharmony_ci
209162306a36Sopenharmony_ci	if ((rdev->family == CHIP_CYPRESS) ||
209262306a36Sopenharmony_ci	    (rdev->family == CHIP_HEMLOCK))
209362306a36Sopenharmony_ci		pi->gfx_clock_gating = false;
209462306a36Sopenharmony_ci	else
209562306a36Sopenharmony_ci		pi->gfx_clock_gating = true;
209662306a36Sopenharmony_ci
209762306a36Sopenharmony_ci	pi->mg_clock_gating = true;
209862306a36Sopenharmony_ci	pi->mgcgtssm = true;
209962306a36Sopenharmony_ci	eg_pi->ls_clock_gating = false;
210062306a36Sopenharmony_ci	eg_pi->sclk_deep_sleep = false;
210162306a36Sopenharmony_ci
210262306a36Sopenharmony_ci	pi->dynamic_pcie_gen2 = true;
210362306a36Sopenharmony_ci
210462306a36Sopenharmony_ci	if (rdev->pm.int_thermal_type != THERMAL_TYPE_NONE)
210562306a36Sopenharmony_ci		pi->thermal_protection = true;
210662306a36Sopenharmony_ci	else
210762306a36Sopenharmony_ci		pi->thermal_protection = false;
210862306a36Sopenharmony_ci
210962306a36Sopenharmony_ci	pi->display_gap = true;
211062306a36Sopenharmony_ci
211162306a36Sopenharmony_ci	if (rdev->flags & RADEON_IS_MOBILITY)
211262306a36Sopenharmony_ci		pi->dcodt = true;
211362306a36Sopenharmony_ci	else
211462306a36Sopenharmony_ci		pi->dcodt = false;
211562306a36Sopenharmony_ci
211662306a36Sopenharmony_ci	pi->ulps = true;
211762306a36Sopenharmony_ci
211862306a36Sopenharmony_ci	eg_pi->dynamic_ac_timing = true;
211962306a36Sopenharmony_ci	eg_pi->abm = true;
212062306a36Sopenharmony_ci	eg_pi->mcls = true;
212162306a36Sopenharmony_ci	eg_pi->light_sleep = true;
212262306a36Sopenharmony_ci	eg_pi->memory_transition = true;
212362306a36Sopenharmony_ci#if defined(CONFIG_ACPI)
212462306a36Sopenharmony_ci	eg_pi->pcie_performance_request =
212562306a36Sopenharmony_ci		radeon_acpi_is_pcie_performance_request_supported(rdev);
212662306a36Sopenharmony_ci#else
212762306a36Sopenharmony_ci	eg_pi->pcie_performance_request = false;
212862306a36Sopenharmony_ci#endif
212962306a36Sopenharmony_ci
213062306a36Sopenharmony_ci	if ((rdev->family == CHIP_CYPRESS) ||
213162306a36Sopenharmony_ci	    (rdev->family == CHIP_HEMLOCK) ||
213262306a36Sopenharmony_ci	    (rdev->family == CHIP_JUNIPER))
213362306a36Sopenharmony_ci		eg_pi->dll_default_on = true;
213462306a36Sopenharmony_ci	else
213562306a36Sopenharmony_ci		eg_pi->dll_default_on = false;
213662306a36Sopenharmony_ci
213762306a36Sopenharmony_ci	eg_pi->sclk_deep_sleep = false;
213862306a36Sopenharmony_ci	pi->mclk_stutter_mode_threshold = 0;
213962306a36Sopenharmony_ci
214062306a36Sopenharmony_ci	pi->sram_end = SMC_RAM_END;
214162306a36Sopenharmony_ci
214262306a36Sopenharmony_ci	return 0;
214362306a36Sopenharmony_ci}
214462306a36Sopenharmony_ci
214562306a36Sopenharmony_civoid cypress_dpm_fini(struct radeon_device *rdev)
214662306a36Sopenharmony_ci{
214762306a36Sopenharmony_ci	int i;
214862306a36Sopenharmony_ci
214962306a36Sopenharmony_ci	for (i = 0; i < rdev->pm.dpm.num_ps; i++) {
215062306a36Sopenharmony_ci		kfree(rdev->pm.dpm.ps[i].ps_priv);
215162306a36Sopenharmony_ci	}
215262306a36Sopenharmony_ci	kfree(rdev->pm.dpm.ps);
215362306a36Sopenharmony_ci	kfree(rdev->pm.dpm.priv);
215462306a36Sopenharmony_ci}
215562306a36Sopenharmony_ci
215662306a36Sopenharmony_cibool cypress_dpm_vblank_too_short(struct radeon_device *rdev)
215762306a36Sopenharmony_ci{
215862306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
215962306a36Sopenharmony_ci	u32 vblank_time = r600_dpm_get_vblank_time(rdev);
216062306a36Sopenharmony_ci	/* we never hit the non-gddr5 limit so disable it */
216162306a36Sopenharmony_ci	u32 switch_limit = pi->mem_gddr5 ? 450 : 0;
216262306a36Sopenharmony_ci
216362306a36Sopenharmony_ci	if (vblank_time < switch_limit)
216462306a36Sopenharmony_ci		return true;
216562306a36Sopenharmony_ci	else
216662306a36Sopenharmony_ci		return false;
216762306a36Sopenharmony_ci
216862306a36Sopenharmony_ci}
2169