xref: /OK3568_Linux_fs/kernel/drivers/gpu/drm/radeon/rv730_dpm.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright 2011 Advanced Micro Devices, Inc.
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Permission is hereby granted, free of charge, to any person obtaining a
5*4882a593Smuzhiyun  * copy of this software and associated documentation files (the "Software"),
6*4882a593Smuzhiyun  * to deal in the Software without restriction, including without limitation
7*4882a593Smuzhiyun  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*4882a593Smuzhiyun  * and/or sell copies of the Software, and to permit persons to whom the
9*4882a593Smuzhiyun  * Software is furnished to do so, subject to the following conditions:
10*4882a593Smuzhiyun  *
11*4882a593Smuzhiyun  * The above copyright notice and this permission notice shall be included in
12*4882a593Smuzhiyun  * all copies or substantial portions of the Software.
13*4882a593Smuzhiyun  *
14*4882a593Smuzhiyun  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15*4882a593Smuzhiyun  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16*4882a593Smuzhiyun  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17*4882a593Smuzhiyun  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18*4882a593Smuzhiyun  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19*4882a593Smuzhiyun  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20*4882a593Smuzhiyun  * OTHER DEALINGS IN THE SOFTWARE.
21*4882a593Smuzhiyun  *
22*4882a593Smuzhiyun  * Authors: Alex Deucher
23*4882a593Smuzhiyun  */
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun #include "radeon.h"
26*4882a593Smuzhiyun #include "rv730d.h"
27*4882a593Smuzhiyun #include "r600_dpm.h"
28*4882a593Smuzhiyun #include "rv770_dpm.h"
29*4882a593Smuzhiyun #include "atom.h"
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun #define MC_CG_ARB_FREQ_F0           0x0a
32*4882a593Smuzhiyun #define MC_CG_ARB_FREQ_F1           0x0b
33*4882a593Smuzhiyun #define MC_CG_ARB_FREQ_F2           0x0c
34*4882a593Smuzhiyun #define MC_CG_ARB_FREQ_F3           0x0d
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun struct rv7xx_ps *rv770_get_ps(struct radeon_ps *rps);
37*4882a593Smuzhiyun struct rv7xx_power_info *rv770_get_pi(struct radeon_device *rdev);
38*4882a593Smuzhiyun 
rv730_populate_sclk_value(struct radeon_device * rdev,u32 engine_clock,RV770_SMC_SCLK_VALUE * sclk)39*4882a593Smuzhiyun int rv730_populate_sclk_value(struct radeon_device *rdev,
40*4882a593Smuzhiyun 			      u32 engine_clock,
41*4882a593Smuzhiyun 			      RV770_SMC_SCLK_VALUE *sclk)
42*4882a593Smuzhiyun {
43*4882a593Smuzhiyun 	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
44*4882a593Smuzhiyun 	struct atom_clock_dividers dividers;
45*4882a593Smuzhiyun 	u32 spll_func_cntl = pi->clk_regs.rv730.cg_spll_func_cntl;
46*4882a593Smuzhiyun 	u32 spll_func_cntl_2 = pi->clk_regs.rv730.cg_spll_func_cntl_2;
47*4882a593Smuzhiyun 	u32 spll_func_cntl_3 = pi->clk_regs.rv730.cg_spll_func_cntl_3;
48*4882a593Smuzhiyun 	u32 cg_spll_spread_spectrum = pi->clk_regs.rv730.cg_spll_spread_spectrum;
49*4882a593Smuzhiyun 	u32 cg_spll_spread_spectrum_2 = pi->clk_regs.rv730.cg_spll_spread_spectrum_2;
50*4882a593Smuzhiyun 	u64 tmp;
51*4882a593Smuzhiyun 	u32 reference_clock = rdev->clock.spll.reference_freq;
52*4882a593Smuzhiyun 	u32 reference_divider, post_divider;
53*4882a593Smuzhiyun 	u32 fbdiv;
54*4882a593Smuzhiyun 	int ret;
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun 	ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
57*4882a593Smuzhiyun 					     engine_clock, false, &dividers);
58*4882a593Smuzhiyun 	if (ret)
59*4882a593Smuzhiyun 		return ret;
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun 	reference_divider = 1 + dividers.ref_div;
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun 	if (dividers.enable_post_div)
64*4882a593Smuzhiyun 		post_divider = ((dividers.post_div >> 4) & 0xf) +
65*4882a593Smuzhiyun 			(dividers.post_div & 0xf) + 2;
66*4882a593Smuzhiyun 	else
67*4882a593Smuzhiyun 		post_divider = 1;
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun 	tmp = (u64) engine_clock * reference_divider * post_divider * 16384;
70*4882a593Smuzhiyun 	do_div(tmp, reference_clock);
71*4882a593Smuzhiyun 	fbdiv = (u32) tmp;
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun 	/* set up registers */
74*4882a593Smuzhiyun 	if (dividers.enable_post_div)
75*4882a593Smuzhiyun 		spll_func_cntl |= SPLL_DIVEN;
76*4882a593Smuzhiyun 	else
77*4882a593Smuzhiyun 		spll_func_cntl &= ~SPLL_DIVEN;
78*4882a593Smuzhiyun 	spll_func_cntl &= ~(SPLL_HILEN_MASK | SPLL_LOLEN_MASK | SPLL_REF_DIV_MASK);
79*4882a593Smuzhiyun 	spll_func_cntl |= SPLL_REF_DIV(dividers.ref_div);
80*4882a593Smuzhiyun 	spll_func_cntl |= SPLL_HILEN((dividers.post_div >> 4) & 0xf);
81*4882a593Smuzhiyun 	spll_func_cntl |= SPLL_LOLEN(dividers.post_div & 0xf);
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun 	spll_func_cntl_2 &= ~SCLK_MUX_SEL_MASK;
84*4882a593Smuzhiyun 	spll_func_cntl_2 |= SCLK_MUX_SEL(2);
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun 	spll_func_cntl_3 &= ~SPLL_FB_DIV_MASK;
87*4882a593Smuzhiyun 	spll_func_cntl_3 |= SPLL_FB_DIV(fbdiv);
88*4882a593Smuzhiyun 	spll_func_cntl_3 |= SPLL_DITHEN;
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun 	if (pi->sclk_ss) {
91*4882a593Smuzhiyun 		struct radeon_atom_ss ss;
92*4882a593Smuzhiyun 		u32 vco_freq = engine_clock * post_divider;
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun 		if (radeon_atombios_get_asic_ss_info(rdev, &ss,
95*4882a593Smuzhiyun 						     ASIC_INTERNAL_ENGINE_SS, vco_freq)) {
96*4882a593Smuzhiyun 			u32 clk_s = reference_clock * 5 / (reference_divider * ss.rate);
97*4882a593Smuzhiyun 			u32 clk_v = ss.percentage * fbdiv / (clk_s * 10000);
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun 			cg_spll_spread_spectrum &= ~CLK_S_MASK;
100*4882a593Smuzhiyun 			cg_spll_spread_spectrum |= CLK_S(clk_s);
101*4882a593Smuzhiyun 			cg_spll_spread_spectrum |= SSEN;
102*4882a593Smuzhiyun 
103*4882a593Smuzhiyun 			cg_spll_spread_spectrum_2 &= ~CLK_V_MASK;
104*4882a593Smuzhiyun 			cg_spll_spread_spectrum_2 |= CLK_V(clk_v);
105*4882a593Smuzhiyun 		}
106*4882a593Smuzhiyun 	}
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun 	sclk->sclk_value = cpu_to_be32(engine_clock);
109*4882a593Smuzhiyun 	sclk->vCG_SPLL_FUNC_CNTL = cpu_to_be32(spll_func_cntl);
110*4882a593Smuzhiyun 	sclk->vCG_SPLL_FUNC_CNTL_2 = cpu_to_be32(spll_func_cntl_2);
111*4882a593Smuzhiyun 	sclk->vCG_SPLL_FUNC_CNTL_3 = cpu_to_be32(spll_func_cntl_3);
112*4882a593Smuzhiyun 	sclk->vCG_SPLL_SPREAD_SPECTRUM = cpu_to_be32(cg_spll_spread_spectrum);
113*4882a593Smuzhiyun 	sclk->vCG_SPLL_SPREAD_SPECTRUM_2 = cpu_to_be32(cg_spll_spread_spectrum_2);
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun 	return 0;
116*4882a593Smuzhiyun }
117*4882a593Smuzhiyun 
rv730_populate_mclk_value(struct radeon_device * rdev,u32 engine_clock,u32 memory_clock,LPRV7XX_SMC_MCLK_VALUE mclk)118*4882a593Smuzhiyun int rv730_populate_mclk_value(struct radeon_device *rdev,
119*4882a593Smuzhiyun 			      u32 engine_clock, u32 memory_clock,
120*4882a593Smuzhiyun 			      LPRV7XX_SMC_MCLK_VALUE mclk)
121*4882a593Smuzhiyun {
122*4882a593Smuzhiyun 	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
123*4882a593Smuzhiyun 	u32 mclk_pwrmgt_cntl = pi->clk_regs.rv730.mclk_pwrmgt_cntl;
124*4882a593Smuzhiyun 	u32 dll_cntl = pi->clk_regs.rv730.dll_cntl;
125*4882a593Smuzhiyun 	u32 mpll_func_cntl = pi->clk_regs.rv730.mpll_func_cntl;
126*4882a593Smuzhiyun 	u32 mpll_func_cntl_2 = pi->clk_regs.rv730.mpll_func_cntl2;
127*4882a593Smuzhiyun 	u32 mpll_func_cntl_3 = pi->clk_regs.rv730.mpll_func_cntl3;
128*4882a593Smuzhiyun 	u32 mpll_ss = pi->clk_regs.rv730.mpll_ss;
129*4882a593Smuzhiyun 	u32 mpll_ss2 = pi->clk_regs.rv730.mpll_ss2;
130*4882a593Smuzhiyun 	struct atom_clock_dividers dividers;
131*4882a593Smuzhiyun 	u32 post_divider, reference_divider;
132*4882a593Smuzhiyun 	int ret;
133*4882a593Smuzhiyun 
134*4882a593Smuzhiyun 	ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_MEMORY_PLL_PARAM,
135*4882a593Smuzhiyun 					     memory_clock, false, &dividers);
136*4882a593Smuzhiyun 	if (ret)
137*4882a593Smuzhiyun 		return ret;
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun 	reference_divider = dividers.ref_div + 1;
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun 	if (dividers.enable_post_div)
142*4882a593Smuzhiyun 		post_divider = ((dividers.post_div >> 4) & 0xf) +
143*4882a593Smuzhiyun 			(dividers.post_div & 0xf) + 2;
144*4882a593Smuzhiyun 	else
145*4882a593Smuzhiyun 		post_divider = 1;
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun 	/* setup the registers */
148*4882a593Smuzhiyun 	if (dividers.enable_post_div)
149*4882a593Smuzhiyun 		mpll_func_cntl |= MPLL_DIVEN;
150*4882a593Smuzhiyun 	else
151*4882a593Smuzhiyun 		mpll_func_cntl &= ~MPLL_DIVEN;
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun 	mpll_func_cntl &= ~(MPLL_REF_DIV_MASK | MPLL_HILEN_MASK | MPLL_LOLEN_MASK);
154*4882a593Smuzhiyun 	mpll_func_cntl |= MPLL_REF_DIV(dividers.ref_div);
155*4882a593Smuzhiyun 	mpll_func_cntl |= MPLL_HILEN((dividers.post_div >> 4) & 0xf);
156*4882a593Smuzhiyun 	mpll_func_cntl |= MPLL_LOLEN(dividers.post_div & 0xf);
157*4882a593Smuzhiyun 
158*4882a593Smuzhiyun 	mpll_func_cntl_3 &= ~MPLL_FB_DIV_MASK;
159*4882a593Smuzhiyun 	mpll_func_cntl_3 |= MPLL_FB_DIV(dividers.fb_div);
160*4882a593Smuzhiyun 	if (dividers.enable_dithen)
161*4882a593Smuzhiyun 		mpll_func_cntl_3 |= MPLL_DITHEN;
162*4882a593Smuzhiyun 	else
163*4882a593Smuzhiyun 		mpll_func_cntl_3 &= ~MPLL_DITHEN;
164*4882a593Smuzhiyun 
165*4882a593Smuzhiyun 	if (pi->mclk_ss) {
166*4882a593Smuzhiyun 		struct radeon_atom_ss ss;
167*4882a593Smuzhiyun 		u32 vco_freq = memory_clock * post_divider;
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun 		if (radeon_atombios_get_asic_ss_info(rdev, &ss,
170*4882a593Smuzhiyun 						     ASIC_INTERNAL_MEMORY_SS, vco_freq)) {
171*4882a593Smuzhiyun 			u32 reference_clock = rdev->clock.mpll.reference_freq;
172*4882a593Smuzhiyun 			u32 clk_s = reference_clock * 5 / (reference_divider * ss.rate);
173*4882a593Smuzhiyun 			u32 clk_v = ss.percentage * dividers.fb_div / (clk_s * 10000);
174*4882a593Smuzhiyun 
175*4882a593Smuzhiyun 			mpll_ss &= ~CLK_S_MASK;
176*4882a593Smuzhiyun 			mpll_ss |= CLK_S(clk_s);
177*4882a593Smuzhiyun 			mpll_ss |= SSEN;
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun 			mpll_ss2 &= ~CLK_V_MASK;
180*4882a593Smuzhiyun 			mpll_ss |= CLK_V(clk_v);
181*4882a593Smuzhiyun 		}
182*4882a593Smuzhiyun 	}
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun 	mclk->mclk730.vMCLK_PWRMGT_CNTL = cpu_to_be32(mclk_pwrmgt_cntl);
186*4882a593Smuzhiyun 	mclk->mclk730.vDLL_CNTL = cpu_to_be32(dll_cntl);
187*4882a593Smuzhiyun 	mclk->mclk730.mclk_value = cpu_to_be32(memory_clock);
188*4882a593Smuzhiyun 	mclk->mclk730.vMPLL_FUNC_CNTL = cpu_to_be32(mpll_func_cntl);
189*4882a593Smuzhiyun 	mclk->mclk730.vMPLL_FUNC_CNTL2 = cpu_to_be32(mpll_func_cntl_2);
190*4882a593Smuzhiyun 	mclk->mclk730.vMPLL_FUNC_CNTL3 = cpu_to_be32(mpll_func_cntl_3);
191*4882a593Smuzhiyun 	mclk->mclk730.vMPLL_SS = cpu_to_be32(mpll_ss);
192*4882a593Smuzhiyun 	mclk->mclk730.vMPLL_SS2 = cpu_to_be32(mpll_ss2);
193*4882a593Smuzhiyun 
194*4882a593Smuzhiyun 	return 0;
195*4882a593Smuzhiyun }
196*4882a593Smuzhiyun 
rv730_read_clock_registers(struct radeon_device * rdev)197*4882a593Smuzhiyun void rv730_read_clock_registers(struct radeon_device *rdev)
198*4882a593Smuzhiyun {
199*4882a593Smuzhiyun 	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
200*4882a593Smuzhiyun 
201*4882a593Smuzhiyun 	pi->clk_regs.rv730.cg_spll_func_cntl =
202*4882a593Smuzhiyun 		RREG32(CG_SPLL_FUNC_CNTL);
203*4882a593Smuzhiyun 	pi->clk_regs.rv730.cg_spll_func_cntl_2 =
204*4882a593Smuzhiyun 		RREG32(CG_SPLL_FUNC_CNTL_2);
205*4882a593Smuzhiyun 	pi->clk_regs.rv730.cg_spll_func_cntl_3 =
206*4882a593Smuzhiyun 		RREG32(CG_SPLL_FUNC_CNTL_3);
207*4882a593Smuzhiyun 	pi->clk_regs.rv730.cg_spll_spread_spectrum =
208*4882a593Smuzhiyun 		RREG32(CG_SPLL_SPREAD_SPECTRUM);
209*4882a593Smuzhiyun 	pi->clk_regs.rv730.cg_spll_spread_spectrum_2 =
210*4882a593Smuzhiyun 		RREG32(CG_SPLL_SPREAD_SPECTRUM_2);
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun 	pi->clk_regs.rv730.mclk_pwrmgt_cntl =
213*4882a593Smuzhiyun 		RREG32(TCI_MCLK_PWRMGT_CNTL);
214*4882a593Smuzhiyun 	pi->clk_regs.rv730.dll_cntl =
215*4882a593Smuzhiyun 		RREG32(TCI_DLL_CNTL);
216*4882a593Smuzhiyun 	pi->clk_regs.rv730.mpll_func_cntl =
217*4882a593Smuzhiyun 		RREG32(CG_MPLL_FUNC_CNTL);
218*4882a593Smuzhiyun 	pi->clk_regs.rv730.mpll_func_cntl2 =
219*4882a593Smuzhiyun 		RREG32(CG_MPLL_FUNC_CNTL_2);
220*4882a593Smuzhiyun 	pi->clk_regs.rv730.mpll_func_cntl3 =
221*4882a593Smuzhiyun 		RREG32(CG_MPLL_FUNC_CNTL_3);
222*4882a593Smuzhiyun 	pi->clk_regs.rv730.mpll_ss =
223*4882a593Smuzhiyun 		RREG32(CG_TCI_MPLL_SPREAD_SPECTRUM);
224*4882a593Smuzhiyun 	pi->clk_regs.rv730.mpll_ss2 =
225*4882a593Smuzhiyun 		RREG32(CG_TCI_MPLL_SPREAD_SPECTRUM_2);
226*4882a593Smuzhiyun }
227*4882a593Smuzhiyun 
rv730_populate_smc_acpi_state(struct radeon_device * rdev,RV770_SMC_STATETABLE * table)228*4882a593Smuzhiyun int rv730_populate_smc_acpi_state(struct radeon_device *rdev,
229*4882a593Smuzhiyun 				  RV770_SMC_STATETABLE *table)
230*4882a593Smuzhiyun {
231*4882a593Smuzhiyun 	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
232*4882a593Smuzhiyun 	u32 mpll_func_cntl = 0;
233*4882a593Smuzhiyun 	u32 mpll_func_cntl_2 = 0 ;
234*4882a593Smuzhiyun 	u32 mpll_func_cntl_3 = 0;
235*4882a593Smuzhiyun 	u32 mclk_pwrmgt_cntl;
236*4882a593Smuzhiyun 	u32 dll_cntl;
237*4882a593Smuzhiyun 	u32 spll_func_cntl;
238*4882a593Smuzhiyun 	u32 spll_func_cntl_2;
239*4882a593Smuzhiyun 	u32 spll_func_cntl_3;
240*4882a593Smuzhiyun 
241*4882a593Smuzhiyun 	table->ACPIState = table->initialState;
242*4882a593Smuzhiyun 	table->ACPIState.flags &= ~PPSMC_SWSTATE_FLAG_DC;
243*4882a593Smuzhiyun 
244*4882a593Smuzhiyun 	if (pi->acpi_vddc) {
245*4882a593Smuzhiyun 		rv770_populate_vddc_value(rdev, pi->acpi_vddc,
246*4882a593Smuzhiyun 					  &table->ACPIState.levels[0].vddc);
247*4882a593Smuzhiyun 		table->ACPIState.levels[0].gen2PCIE = pi->pcie_gen2 ?
248*4882a593Smuzhiyun 			pi->acpi_pcie_gen2 : 0;
249*4882a593Smuzhiyun 		table->ACPIState.levels[0].gen2XSP =
250*4882a593Smuzhiyun 			pi->acpi_pcie_gen2;
251*4882a593Smuzhiyun 	} else {
252*4882a593Smuzhiyun 		rv770_populate_vddc_value(rdev, pi->min_vddc_in_table,
253*4882a593Smuzhiyun 					  &table->ACPIState.levels[0].vddc);
254*4882a593Smuzhiyun 		table->ACPIState.levels[0].gen2PCIE = 0;
255*4882a593Smuzhiyun 	}
256*4882a593Smuzhiyun 
257*4882a593Smuzhiyun 	mpll_func_cntl = pi->clk_regs.rv730.mpll_func_cntl;
258*4882a593Smuzhiyun 	mpll_func_cntl_2 = pi->clk_regs.rv730.mpll_func_cntl2;
259*4882a593Smuzhiyun 	mpll_func_cntl_3 = pi->clk_regs.rv730.mpll_func_cntl3;
260*4882a593Smuzhiyun 
261*4882a593Smuzhiyun 	mpll_func_cntl |= MPLL_RESET | MPLL_BYPASS_EN;
262*4882a593Smuzhiyun 	mpll_func_cntl &= ~MPLL_SLEEP;
263*4882a593Smuzhiyun 
264*4882a593Smuzhiyun 	mpll_func_cntl_2 &= ~MCLK_MUX_SEL_MASK;
265*4882a593Smuzhiyun 	mpll_func_cntl_2 |= MCLK_MUX_SEL(1);
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun 	mclk_pwrmgt_cntl = (MRDCKA_RESET |
268*4882a593Smuzhiyun 			    MRDCKB_RESET |
269*4882a593Smuzhiyun 			    MRDCKC_RESET |
270*4882a593Smuzhiyun 			    MRDCKD_RESET |
271*4882a593Smuzhiyun 			    MRDCKE_RESET |
272*4882a593Smuzhiyun 			    MRDCKF_RESET |
273*4882a593Smuzhiyun 			    MRDCKG_RESET |
274*4882a593Smuzhiyun 			    MRDCKH_RESET |
275*4882a593Smuzhiyun 			    MRDCKA_SLEEP |
276*4882a593Smuzhiyun 			    MRDCKB_SLEEP |
277*4882a593Smuzhiyun 			    MRDCKC_SLEEP |
278*4882a593Smuzhiyun 			    MRDCKD_SLEEP |
279*4882a593Smuzhiyun 			    MRDCKE_SLEEP |
280*4882a593Smuzhiyun 			    MRDCKF_SLEEP |
281*4882a593Smuzhiyun 			    MRDCKG_SLEEP |
282*4882a593Smuzhiyun 			    MRDCKH_SLEEP);
283*4882a593Smuzhiyun 
284*4882a593Smuzhiyun 	dll_cntl = 0xff000000;
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun 	spll_func_cntl = pi->clk_regs.rv730.cg_spll_func_cntl;
287*4882a593Smuzhiyun 	spll_func_cntl_2 = pi->clk_regs.rv730.cg_spll_func_cntl_2;
288*4882a593Smuzhiyun 	spll_func_cntl_3 = pi->clk_regs.rv730.cg_spll_func_cntl_3;
289*4882a593Smuzhiyun 
290*4882a593Smuzhiyun 	spll_func_cntl |= SPLL_RESET | SPLL_BYPASS_EN;
291*4882a593Smuzhiyun 	spll_func_cntl &= ~SPLL_SLEEP;
292*4882a593Smuzhiyun 
293*4882a593Smuzhiyun 	spll_func_cntl_2 &= ~SCLK_MUX_SEL_MASK;
294*4882a593Smuzhiyun 	spll_func_cntl_2 |= SCLK_MUX_SEL(4);
295*4882a593Smuzhiyun 
296*4882a593Smuzhiyun 	table->ACPIState.levels[0].mclk.mclk730.vMPLL_FUNC_CNTL = cpu_to_be32(mpll_func_cntl);
297*4882a593Smuzhiyun 	table->ACPIState.levels[0].mclk.mclk730.vMPLL_FUNC_CNTL2 = cpu_to_be32(mpll_func_cntl_2);
298*4882a593Smuzhiyun 	table->ACPIState.levels[0].mclk.mclk730.vMPLL_FUNC_CNTL3 = cpu_to_be32(mpll_func_cntl_3);
299*4882a593Smuzhiyun 	table->ACPIState.levels[0].mclk.mclk730.vMCLK_PWRMGT_CNTL = cpu_to_be32(mclk_pwrmgt_cntl);
300*4882a593Smuzhiyun 	table->ACPIState.levels[0].mclk.mclk730.vDLL_CNTL = cpu_to_be32(dll_cntl);
301*4882a593Smuzhiyun 
302*4882a593Smuzhiyun 	table->ACPIState.levels[0].mclk.mclk730.mclk_value = 0;
303*4882a593Smuzhiyun 
304*4882a593Smuzhiyun 	table->ACPIState.levels[0].sclk.vCG_SPLL_FUNC_CNTL = cpu_to_be32(spll_func_cntl);
305*4882a593Smuzhiyun 	table->ACPIState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_2 = cpu_to_be32(spll_func_cntl_2);
306*4882a593Smuzhiyun 	table->ACPIState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_3 = cpu_to_be32(spll_func_cntl_3);
307*4882a593Smuzhiyun 
308*4882a593Smuzhiyun 	table->ACPIState.levels[0].sclk.sclk_value = 0;
309*4882a593Smuzhiyun 
310*4882a593Smuzhiyun 	rv770_populate_mvdd_value(rdev, 0, &table->ACPIState.levels[0].mvdd);
311*4882a593Smuzhiyun 
312*4882a593Smuzhiyun 	table->ACPIState.levels[1] = table->ACPIState.levels[0];
313*4882a593Smuzhiyun 	table->ACPIState.levels[2] = table->ACPIState.levels[0];
314*4882a593Smuzhiyun 
315*4882a593Smuzhiyun 	return 0;
316*4882a593Smuzhiyun }
317*4882a593Smuzhiyun 
rv730_populate_smc_initial_state(struct radeon_device * rdev,struct radeon_ps * radeon_state,RV770_SMC_STATETABLE * table)318*4882a593Smuzhiyun int rv730_populate_smc_initial_state(struct radeon_device *rdev,
319*4882a593Smuzhiyun 				     struct radeon_ps *radeon_state,
320*4882a593Smuzhiyun 				     RV770_SMC_STATETABLE *table)
321*4882a593Smuzhiyun {
322*4882a593Smuzhiyun 	struct rv7xx_ps *initial_state = rv770_get_ps(radeon_state);
323*4882a593Smuzhiyun 	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
324*4882a593Smuzhiyun 	u32 a_t;
325*4882a593Smuzhiyun 
326*4882a593Smuzhiyun 	table->initialState.levels[0].mclk.mclk730.vMPLL_FUNC_CNTL =
327*4882a593Smuzhiyun 		cpu_to_be32(pi->clk_regs.rv730.mpll_func_cntl);
328*4882a593Smuzhiyun 	table->initialState.levels[0].mclk.mclk730.vMPLL_FUNC_CNTL2 =
329*4882a593Smuzhiyun 		cpu_to_be32(pi->clk_regs.rv730.mpll_func_cntl2);
330*4882a593Smuzhiyun 	table->initialState.levels[0].mclk.mclk730.vMPLL_FUNC_CNTL3 =
331*4882a593Smuzhiyun 		cpu_to_be32(pi->clk_regs.rv730.mpll_func_cntl3);
332*4882a593Smuzhiyun 	table->initialState.levels[0].mclk.mclk730.vMCLK_PWRMGT_CNTL =
333*4882a593Smuzhiyun 		cpu_to_be32(pi->clk_regs.rv730.mclk_pwrmgt_cntl);
334*4882a593Smuzhiyun 	table->initialState.levels[0].mclk.mclk730.vDLL_CNTL =
335*4882a593Smuzhiyun 		cpu_to_be32(pi->clk_regs.rv730.dll_cntl);
336*4882a593Smuzhiyun 	table->initialState.levels[0].mclk.mclk730.vMPLL_SS =
337*4882a593Smuzhiyun 		cpu_to_be32(pi->clk_regs.rv730.mpll_ss);
338*4882a593Smuzhiyun 	table->initialState.levels[0].mclk.mclk730.vMPLL_SS2 =
339*4882a593Smuzhiyun 		cpu_to_be32(pi->clk_regs.rv730.mpll_ss2);
340*4882a593Smuzhiyun 
341*4882a593Smuzhiyun 	table->initialState.levels[0].mclk.mclk730.mclk_value =
342*4882a593Smuzhiyun 		cpu_to_be32(initial_state->low.mclk);
343*4882a593Smuzhiyun 
344*4882a593Smuzhiyun 	table->initialState.levels[0].sclk.vCG_SPLL_FUNC_CNTL =
345*4882a593Smuzhiyun 		cpu_to_be32(pi->clk_regs.rv730.cg_spll_func_cntl);
346*4882a593Smuzhiyun 	table->initialState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_2 =
347*4882a593Smuzhiyun 		cpu_to_be32(pi->clk_regs.rv730.cg_spll_func_cntl_2);
348*4882a593Smuzhiyun 	table->initialState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_3 =
349*4882a593Smuzhiyun 		cpu_to_be32(pi->clk_regs.rv730.cg_spll_func_cntl_3);
350*4882a593Smuzhiyun 	table->initialState.levels[0].sclk.vCG_SPLL_SPREAD_SPECTRUM =
351*4882a593Smuzhiyun 		cpu_to_be32(pi->clk_regs.rv730.cg_spll_spread_spectrum);
352*4882a593Smuzhiyun 	table->initialState.levels[0].sclk.vCG_SPLL_SPREAD_SPECTRUM_2 =
353*4882a593Smuzhiyun 		cpu_to_be32(pi->clk_regs.rv730.cg_spll_spread_spectrum_2);
354*4882a593Smuzhiyun 
355*4882a593Smuzhiyun 	table->initialState.levels[0].sclk.sclk_value =
356*4882a593Smuzhiyun 		cpu_to_be32(initial_state->low.sclk);
357*4882a593Smuzhiyun 
358*4882a593Smuzhiyun 	table->initialState.levels[0].arbValue = MC_CG_ARB_FREQ_F0;
359*4882a593Smuzhiyun 
360*4882a593Smuzhiyun 	table->initialState.levels[0].seqValue =
361*4882a593Smuzhiyun 		rv770_get_seq_value(rdev, &initial_state->low);
362*4882a593Smuzhiyun 
363*4882a593Smuzhiyun 	rv770_populate_vddc_value(rdev,
364*4882a593Smuzhiyun 				  initial_state->low.vddc,
365*4882a593Smuzhiyun 				  &table->initialState.levels[0].vddc);
366*4882a593Smuzhiyun 	rv770_populate_initial_mvdd_value(rdev,
367*4882a593Smuzhiyun 					  &table->initialState.levels[0].mvdd);
368*4882a593Smuzhiyun 
369*4882a593Smuzhiyun 	a_t = CG_R(0xffff) | CG_L(0);
370*4882a593Smuzhiyun 
371*4882a593Smuzhiyun 	table->initialState.levels[0].aT = cpu_to_be32(a_t);
372*4882a593Smuzhiyun 
373*4882a593Smuzhiyun 	table->initialState.levels[0].bSP = cpu_to_be32(pi->dsp);
374*4882a593Smuzhiyun 
375*4882a593Smuzhiyun 	if (pi->boot_in_gen2)
376*4882a593Smuzhiyun 		table->initialState.levels[0].gen2PCIE = 1;
377*4882a593Smuzhiyun 	else
378*4882a593Smuzhiyun 		table->initialState.levels[0].gen2PCIE = 0;
379*4882a593Smuzhiyun 	if (initial_state->low.flags & ATOM_PPLIB_R600_FLAGS_PCIEGEN2)
380*4882a593Smuzhiyun 		table->initialState.levels[0].gen2XSP = 1;
381*4882a593Smuzhiyun 	else
382*4882a593Smuzhiyun 		table->initialState.levels[0].gen2XSP = 0;
383*4882a593Smuzhiyun 
384*4882a593Smuzhiyun 	table->initialState.levels[1] = table->initialState.levels[0];
385*4882a593Smuzhiyun 	table->initialState.levels[2] = table->initialState.levels[0];
386*4882a593Smuzhiyun 
387*4882a593Smuzhiyun 	table->initialState.flags |= PPSMC_SWSTATE_FLAG_DC;
388*4882a593Smuzhiyun 
389*4882a593Smuzhiyun 	return 0;
390*4882a593Smuzhiyun }
391*4882a593Smuzhiyun 
rv730_program_memory_timing_parameters(struct radeon_device * rdev,struct radeon_ps * radeon_state)392*4882a593Smuzhiyun void rv730_program_memory_timing_parameters(struct radeon_device *rdev,
393*4882a593Smuzhiyun 					    struct radeon_ps *radeon_state)
394*4882a593Smuzhiyun {
395*4882a593Smuzhiyun 	struct rv7xx_ps *state = rv770_get_ps(radeon_state);
396*4882a593Smuzhiyun 	u32 arb_refresh_rate = 0;
397*4882a593Smuzhiyun 	u32 dram_timing = 0;
398*4882a593Smuzhiyun 	u32 dram_timing2 = 0;
399*4882a593Smuzhiyun 	u32 old_dram_timing = 0;
400*4882a593Smuzhiyun 	u32 old_dram_timing2 = 0;
401*4882a593Smuzhiyun 
402*4882a593Smuzhiyun 	arb_refresh_rate = RREG32(MC_ARB_RFSH_RATE) &
403*4882a593Smuzhiyun 		~(POWERMODE1_MASK | POWERMODE2_MASK | POWERMODE3_MASK);
404*4882a593Smuzhiyun 	arb_refresh_rate |=
405*4882a593Smuzhiyun 		(POWERMODE1(rv770_calculate_memory_refresh_rate(rdev, state->low.sclk)) |
406*4882a593Smuzhiyun 		 POWERMODE2(rv770_calculate_memory_refresh_rate(rdev, state->medium.sclk)) |
407*4882a593Smuzhiyun 		 POWERMODE3(rv770_calculate_memory_refresh_rate(rdev, state->high.sclk)));
408*4882a593Smuzhiyun 	WREG32(MC_ARB_RFSH_RATE, arb_refresh_rate);
409*4882a593Smuzhiyun 
410*4882a593Smuzhiyun 	/* save the boot dram timings */
411*4882a593Smuzhiyun 	old_dram_timing = RREG32(MC_ARB_DRAM_TIMING);
412*4882a593Smuzhiyun 	old_dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2);
413*4882a593Smuzhiyun 
414*4882a593Smuzhiyun 	radeon_atom_set_engine_dram_timings(rdev,
415*4882a593Smuzhiyun 					    state->high.sclk,
416*4882a593Smuzhiyun 					    state->high.mclk);
417*4882a593Smuzhiyun 
418*4882a593Smuzhiyun 	dram_timing = RREG32(MC_ARB_DRAM_TIMING);
419*4882a593Smuzhiyun 	dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2);
420*4882a593Smuzhiyun 
421*4882a593Smuzhiyun 	WREG32(MC_ARB_DRAM_TIMING_3, dram_timing);
422*4882a593Smuzhiyun 	WREG32(MC_ARB_DRAM_TIMING2_3, dram_timing2);
423*4882a593Smuzhiyun 
424*4882a593Smuzhiyun 	radeon_atom_set_engine_dram_timings(rdev,
425*4882a593Smuzhiyun 					    state->medium.sclk,
426*4882a593Smuzhiyun 					    state->medium.mclk);
427*4882a593Smuzhiyun 
428*4882a593Smuzhiyun 	dram_timing = RREG32(MC_ARB_DRAM_TIMING);
429*4882a593Smuzhiyun 	dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2);
430*4882a593Smuzhiyun 
431*4882a593Smuzhiyun 	WREG32(MC_ARB_DRAM_TIMING_2, dram_timing);
432*4882a593Smuzhiyun 	WREG32(MC_ARB_DRAM_TIMING2_2, dram_timing2);
433*4882a593Smuzhiyun 
434*4882a593Smuzhiyun 	radeon_atom_set_engine_dram_timings(rdev,
435*4882a593Smuzhiyun 					    state->low.sclk,
436*4882a593Smuzhiyun 					    state->low.mclk);
437*4882a593Smuzhiyun 
438*4882a593Smuzhiyun 	dram_timing = RREG32(MC_ARB_DRAM_TIMING);
439*4882a593Smuzhiyun 	dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2);
440*4882a593Smuzhiyun 
441*4882a593Smuzhiyun 	WREG32(MC_ARB_DRAM_TIMING_1, dram_timing);
442*4882a593Smuzhiyun 	WREG32(MC_ARB_DRAM_TIMING2_1, dram_timing2);
443*4882a593Smuzhiyun 
444*4882a593Smuzhiyun 	/* restore the boot dram timings */
445*4882a593Smuzhiyun 	WREG32(MC_ARB_DRAM_TIMING, old_dram_timing);
446*4882a593Smuzhiyun 	WREG32(MC_ARB_DRAM_TIMING2, old_dram_timing2);
447*4882a593Smuzhiyun 
448*4882a593Smuzhiyun }
449*4882a593Smuzhiyun 
rv730_start_dpm(struct radeon_device * rdev)450*4882a593Smuzhiyun void rv730_start_dpm(struct radeon_device *rdev)
451*4882a593Smuzhiyun {
452*4882a593Smuzhiyun 	WREG32_P(SCLK_PWRMGT_CNTL, 0, ~SCLK_PWRMGT_OFF);
453*4882a593Smuzhiyun 
454*4882a593Smuzhiyun 	WREG32_P(TCI_MCLK_PWRMGT_CNTL, 0, ~MPLL_PWRMGT_OFF);
455*4882a593Smuzhiyun 
456*4882a593Smuzhiyun 	WREG32_P(GENERAL_PWRMGT, GLOBAL_PWRMGT_EN, ~GLOBAL_PWRMGT_EN);
457*4882a593Smuzhiyun }
458*4882a593Smuzhiyun 
rv730_stop_dpm(struct radeon_device * rdev)459*4882a593Smuzhiyun void rv730_stop_dpm(struct radeon_device *rdev)
460*4882a593Smuzhiyun {
461*4882a593Smuzhiyun 	PPSMC_Result result;
462*4882a593Smuzhiyun 
463*4882a593Smuzhiyun 	result = rv770_send_msg_to_smc(rdev, PPSMC_MSG_TwoLevelsDisabled);
464*4882a593Smuzhiyun 
465*4882a593Smuzhiyun 	if (result != PPSMC_Result_OK)
466*4882a593Smuzhiyun 		DRM_DEBUG("Could not force DPM to low\n");
467*4882a593Smuzhiyun 
468*4882a593Smuzhiyun 	WREG32_P(GENERAL_PWRMGT, 0, ~GLOBAL_PWRMGT_EN);
469*4882a593Smuzhiyun 
470*4882a593Smuzhiyun 	WREG32_P(SCLK_PWRMGT_CNTL, SCLK_PWRMGT_OFF, ~SCLK_PWRMGT_OFF);
471*4882a593Smuzhiyun 
472*4882a593Smuzhiyun 	WREG32_P(TCI_MCLK_PWRMGT_CNTL, MPLL_PWRMGT_OFF, ~MPLL_PWRMGT_OFF);
473*4882a593Smuzhiyun }
474*4882a593Smuzhiyun 
rv730_program_dcodt(struct radeon_device * rdev,bool use_dcodt)475*4882a593Smuzhiyun void rv730_program_dcodt(struct radeon_device *rdev, bool use_dcodt)
476*4882a593Smuzhiyun {
477*4882a593Smuzhiyun 	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
478*4882a593Smuzhiyun 	u32 i = use_dcodt ? 0 : 1;
479*4882a593Smuzhiyun 	u32 mc4_io_pad_cntl;
480*4882a593Smuzhiyun 
481*4882a593Smuzhiyun 	mc4_io_pad_cntl = RREG32(MC4_IO_DQ_PAD_CNTL_D0_I0);
482*4882a593Smuzhiyun 	mc4_io_pad_cntl &= 0xFFFFFF00;
483*4882a593Smuzhiyun 	mc4_io_pad_cntl |= pi->odt_value_0[i];
484*4882a593Smuzhiyun 	WREG32(MC4_IO_DQ_PAD_CNTL_D0_I0, mc4_io_pad_cntl);
485*4882a593Smuzhiyun 	WREG32(MC4_IO_DQ_PAD_CNTL_D0_I1, mc4_io_pad_cntl);
486*4882a593Smuzhiyun 
487*4882a593Smuzhiyun 	mc4_io_pad_cntl = RREG32(MC4_IO_QS_PAD_CNTL_D0_I0);
488*4882a593Smuzhiyun 	mc4_io_pad_cntl &= 0xFFFFFF00;
489*4882a593Smuzhiyun 	mc4_io_pad_cntl |= pi->odt_value_1[i];
490*4882a593Smuzhiyun 	WREG32(MC4_IO_QS_PAD_CNTL_D0_I0, mc4_io_pad_cntl);
491*4882a593Smuzhiyun 	WREG32(MC4_IO_QS_PAD_CNTL_D0_I1, mc4_io_pad_cntl);
492*4882a593Smuzhiyun }
493*4882a593Smuzhiyun 
rv730_get_odt_values(struct radeon_device * rdev)494*4882a593Smuzhiyun void rv730_get_odt_values(struct radeon_device *rdev)
495*4882a593Smuzhiyun {
496*4882a593Smuzhiyun 	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
497*4882a593Smuzhiyun 	u32 mc4_io_pad_cntl;
498*4882a593Smuzhiyun 
499*4882a593Smuzhiyun 	pi->odt_value_0[0] = (u8)0;
500*4882a593Smuzhiyun 	pi->odt_value_1[0] = (u8)0x80;
501*4882a593Smuzhiyun 
502*4882a593Smuzhiyun 	mc4_io_pad_cntl = RREG32(MC4_IO_DQ_PAD_CNTL_D0_I0);
503*4882a593Smuzhiyun 	pi->odt_value_0[1] = (u8)(mc4_io_pad_cntl & 0xff);
504*4882a593Smuzhiyun 
505*4882a593Smuzhiyun 	mc4_io_pad_cntl = RREG32(MC4_IO_QS_PAD_CNTL_D0_I0);
506*4882a593Smuzhiyun 	pi->odt_value_1[1] = (u8)(mc4_io_pad_cntl & 0xff);
507*4882a593Smuzhiyun }
508