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, ÷rs);
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, ÷rs);
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