18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright 2011 Advanced Micro Devices, Inc. 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 58c2ecf20Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 68c2ecf20Sopenharmony_ci * to deal in the Software without restriction, including without limitation 78c2ecf20Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 88c2ecf20Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 98c2ecf20Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * The above copyright notice and this permission notice shall be included in 128c2ecf20Sopenharmony_ci * all copies or substantial portions of the Software. 138c2ecf20Sopenharmony_ci * 148c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 158c2ecf20Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 168c2ecf20Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 178c2ecf20Sopenharmony_ci * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 188c2ecf20Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 198c2ecf20Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 208c2ecf20Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE. 218c2ecf20Sopenharmony_ci * 228c2ecf20Sopenharmony_ci * Authors: Alex Deucher 238c2ecf20Sopenharmony_ci */ 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci#include "radeon.h" 268c2ecf20Sopenharmony_ci#include "rv730d.h" 278c2ecf20Sopenharmony_ci#include "r600_dpm.h" 288c2ecf20Sopenharmony_ci#include "rv770_dpm.h" 298c2ecf20Sopenharmony_ci#include "atom.h" 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci#define MC_CG_ARB_FREQ_F0 0x0a 328c2ecf20Sopenharmony_ci#define MC_CG_ARB_FREQ_F1 0x0b 338c2ecf20Sopenharmony_ci#define MC_CG_ARB_FREQ_F2 0x0c 348c2ecf20Sopenharmony_ci#define MC_CG_ARB_FREQ_F3 0x0d 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_cistruct rv7xx_ps *rv770_get_ps(struct radeon_ps *rps); 378c2ecf20Sopenharmony_cistruct rv7xx_power_info *rv770_get_pi(struct radeon_device *rdev); 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ciint rv730_populate_sclk_value(struct radeon_device *rdev, 408c2ecf20Sopenharmony_ci u32 engine_clock, 418c2ecf20Sopenharmony_ci RV770_SMC_SCLK_VALUE *sclk) 428c2ecf20Sopenharmony_ci{ 438c2ecf20Sopenharmony_ci struct rv7xx_power_info *pi = rv770_get_pi(rdev); 448c2ecf20Sopenharmony_ci struct atom_clock_dividers dividers; 458c2ecf20Sopenharmony_ci u32 spll_func_cntl = pi->clk_regs.rv730.cg_spll_func_cntl; 468c2ecf20Sopenharmony_ci u32 spll_func_cntl_2 = pi->clk_regs.rv730.cg_spll_func_cntl_2; 478c2ecf20Sopenharmony_ci u32 spll_func_cntl_3 = pi->clk_regs.rv730.cg_spll_func_cntl_3; 488c2ecf20Sopenharmony_ci u32 cg_spll_spread_spectrum = pi->clk_regs.rv730.cg_spll_spread_spectrum; 498c2ecf20Sopenharmony_ci u32 cg_spll_spread_spectrum_2 = pi->clk_regs.rv730.cg_spll_spread_spectrum_2; 508c2ecf20Sopenharmony_ci u64 tmp; 518c2ecf20Sopenharmony_ci u32 reference_clock = rdev->clock.spll.reference_freq; 528c2ecf20Sopenharmony_ci u32 reference_divider, post_divider; 538c2ecf20Sopenharmony_ci u32 fbdiv; 548c2ecf20Sopenharmony_ci int ret; 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM, 578c2ecf20Sopenharmony_ci engine_clock, false, ÷rs); 588c2ecf20Sopenharmony_ci if (ret) 598c2ecf20Sopenharmony_ci return ret; 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci reference_divider = 1 + dividers.ref_div; 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci if (dividers.enable_post_div) 648c2ecf20Sopenharmony_ci post_divider = ((dividers.post_div >> 4) & 0xf) + 658c2ecf20Sopenharmony_ci (dividers.post_div & 0xf) + 2; 668c2ecf20Sopenharmony_ci else 678c2ecf20Sopenharmony_ci post_divider = 1; 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci tmp = (u64) engine_clock * reference_divider * post_divider * 16384; 708c2ecf20Sopenharmony_ci do_div(tmp, reference_clock); 718c2ecf20Sopenharmony_ci fbdiv = (u32) tmp; 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci /* set up registers */ 748c2ecf20Sopenharmony_ci if (dividers.enable_post_div) 758c2ecf20Sopenharmony_ci spll_func_cntl |= SPLL_DIVEN; 768c2ecf20Sopenharmony_ci else 778c2ecf20Sopenharmony_ci spll_func_cntl &= ~SPLL_DIVEN; 788c2ecf20Sopenharmony_ci spll_func_cntl &= ~(SPLL_HILEN_MASK | SPLL_LOLEN_MASK | SPLL_REF_DIV_MASK); 798c2ecf20Sopenharmony_ci spll_func_cntl |= SPLL_REF_DIV(dividers.ref_div); 808c2ecf20Sopenharmony_ci spll_func_cntl |= SPLL_HILEN((dividers.post_div >> 4) & 0xf); 818c2ecf20Sopenharmony_ci spll_func_cntl |= SPLL_LOLEN(dividers.post_div & 0xf); 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci spll_func_cntl_2 &= ~SCLK_MUX_SEL_MASK; 848c2ecf20Sopenharmony_ci spll_func_cntl_2 |= SCLK_MUX_SEL(2); 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci spll_func_cntl_3 &= ~SPLL_FB_DIV_MASK; 878c2ecf20Sopenharmony_ci spll_func_cntl_3 |= SPLL_FB_DIV(fbdiv); 888c2ecf20Sopenharmony_ci spll_func_cntl_3 |= SPLL_DITHEN; 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci if (pi->sclk_ss) { 918c2ecf20Sopenharmony_ci struct radeon_atom_ss ss; 928c2ecf20Sopenharmony_ci u32 vco_freq = engine_clock * post_divider; 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci if (radeon_atombios_get_asic_ss_info(rdev, &ss, 958c2ecf20Sopenharmony_ci ASIC_INTERNAL_ENGINE_SS, vco_freq)) { 968c2ecf20Sopenharmony_ci u32 clk_s = reference_clock * 5 / (reference_divider * ss.rate); 978c2ecf20Sopenharmony_ci u32 clk_v = ss.percentage * fbdiv / (clk_s * 10000); 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci cg_spll_spread_spectrum &= ~CLK_S_MASK; 1008c2ecf20Sopenharmony_ci cg_spll_spread_spectrum |= CLK_S(clk_s); 1018c2ecf20Sopenharmony_ci cg_spll_spread_spectrum |= SSEN; 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci cg_spll_spread_spectrum_2 &= ~CLK_V_MASK; 1048c2ecf20Sopenharmony_ci cg_spll_spread_spectrum_2 |= CLK_V(clk_v); 1058c2ecf20Sopenharmony_ci } 1068c2ecf20Sopenharmony_ci } 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci sclk->sclk_value = cpu_to_be32(engine_clock); 1098c2ecf20Sopenharmony_ci sclk->vCG_SPLL_FUNC_CNTL = cpu_to_be32(spll_func_cntl); 1108c2ecf20Sopenharmony_ci sclk->vCG_SPLL_FUNC_CNTL_2 = cpu_to_be32(spll_func_cntl_2); 1118c2ecf20Sopenharmony_ci sclk->vCG_SPLL_FUNC_CNTL_3 = cpu_to_be32(spll_func_cntl_3); 1128c2ecf20Sopenharmony_ci sclk->vCG_SPLL_SPREAD_SPECTRUM = cpu_to_be32(cg_spll_spread_spectrum); 1138c2ecf20Sopenharmony_ci sclk->vCG_SPLL_SPREAD_SPECTRUM_2 = cpu_to_be32(cg_spll_spread_spectrum_2); 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci return 0; 1168c2ecf20Sopenharmony_ci} 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ciint rv730_populate_mclk_value(struct radeon_device *rdev, 1198c2ecf20Sopenharmony_ci u32 engine_clock, u32 memory_clock, 1208c2ecf20Sopenharmony_ci LPRV7XX_SMC_MCLK_VALUE mclk) 1218c2ecf20Sopenharmony_ci{ 1228c2ecf20Sopenharmony_ci struct rv7xx_power_info *pi = rv770_get_pi(rdev); 1238c2ecf20Sopenharmony_ci u32 mclk_pwrmgt_cntl = pi->clk_regs.rv730.mclk_pwrmgt_cntl; 1248c2ecf20Sopenharmony_ci u32 dll_cntl = pi->clk_regs.rv730.dll_cntl; 1258c2ecf20Sopenharmony_ci u32 mpll_func_cntl = pi->clk_regs.rv730.mpll_func_cntl; 1268c2ecf20Sopenharmony_ci u32 mpll_func_cntl_2 = pi->clk_regs.rv730.mpll_func_cntl2; 1278c2ecf20Sopenharmony_ci u32 mpll_func_cntl_3 = pi->clk_regs.rv730.mpll_func_cntl3; 1288c2ecf20Sopenharmony_ci u32 mpll_ss = pi->clk_regs.rv730.mpll_ss; 1298c2ecf20Sopenharmony_ci u32 mpll_ss2 = pi->clk_regs.rv730.mpll_ss2; 1308c2ecf20Sopenharmony_ci struct atom_clock_dividers dividers; 1318c2ecf20Sopenharmony_ci u32 post_divider, reference_divider; 1328c2ecf20Sopenharmony_ci int ret; 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_MEMORY_PLL_PARAM, 1358c2ecf20Sopenharmony_ci memory_clock, false, ÷rs); 1368c2ecf20Sopenharmony_ci if (ret) 1378c2ecf20Sopenharmony_ci return ret; 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci reference_divider = dividers.ref_div + 1; 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci if (dividers.enable_post_div) 1428c2ecf20Sopenharmony_ci post_divider = ((dividers.post_div >> 4) & 0xf) + 1438c2ecf20Sopenharmony_ci (dividers.post_div & 0xf) + 2; 1448c2ecf20Sopenharmony_ci else 1458c2ecf20Sopenharmony_ci post_divider = 1; 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci /* setup the registers */ 1488c2ecf20Sopenharmony_ci if (dividers.enable_post_div) 1498c2ecf20Sopenharmony_ci mpll_func_cntl |= MPLL_DIVEN; 1508c2ecf20Sopenharmony_ci else 1518c2ecf20Sopenharmony_ci mpll_func_cntl &= ~MPLL_DIVEN; 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci mpll_func_cntl &= ~(MPLL_REF_DIV_MASK | MPLL_HILEN_MASK | MPLL_LOLEN_MASK); 1548c2ecf20Sopenharmony_ci mpll_func_cntl |= MPLL_REF_DIV(dividers.ref_div); 1558c2ecf20Sopenharmony_ci mpll_func_cntl |= MPLL_HILEN((dividers.post_div >> 4) & 0xf); 1568c2ecf20Sopenharmony_ci mpll_func_cntl |= MPLL_LOLEN(dividers.post_div & 0xf); 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci mpll_func_cntl_3 &= ~MPLL_FB_DIV_MASK; 1598c2ecf20Sopenharmony_ci mpll_func_cntl_3 |= MPLL_FB_DIV(dividers.fb_div); 1608c2ecf20Sopenharmony_ci if (dividers.enable_dithen) 1618c2ecf20Sopenharmony_ci mpll_func_cntl_3 |= MPLL_DITHEN; 1628c2ecf20Sopenharmony_ci else 1638c2ecf20Sopenharmony_ci mpll_func_cntl_3 &= ~MPLL_DITHEN; 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci if (pi->mclk_ss) { 1668c2ecf20Sopenharmony_ci struct radeon_atom_ss ss; 1678c2ecf20Sopenharmony_ci u32 vco_freq = memory_clock * post_divider; 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci if (radeon_atombios_get_asic_ss_info(rdev, &ss, 1708c2ecf20Sopenharmony_ci ASIC_INTERNAL_MEMORY_SS, vco_freq)) { 1718c2ecf20Sopenharmony_ci u32 reference_clock = rdev->clock.mpll.reference_freq; 1728c2ecf20Sopenharmony_ci u32 clk_s = reference_clock * 5 / (reference_divider * ss.rate); 1738c2ecf20Sopenharmony_ci u32 clk_v = ss.percentage * dividers.fb_div / (clk_s * 10000); 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci mpll_ss &= ~CLK_S_MASK; 1768c2ecf20Sopenharmony_ci mpll_ss |= CLK_S(clk_s); 1778c2ecf20Sopenharmony_ci mpll_ss |= SSEN; 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci mpll_ss2 &= ~CLK_V_MASK; 1808c2ecf20Sopenharmony_ci mpll_ss |= CLK_V(clk_v); 1818c2ecf20Sopenharmony_ci } 1828c2ecf20Sopenharmony_ci } 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci mclk->mclk730.vMCLK_PWRMGT_CNTL = cpu_to_be32(mclk_pwrmgt_cntl); 1868c2ecf20Sopenharmony_ci mclk->mclk730.vDLL_CNTL = cpu_to_be32(dll_cntl); 1878c2ecf20Sopenharmony_ci mclk->mclk730.mclk_value = cpu_to_be32(memory_clock); 1888c2ecf20Sopenharmony_ci mclk->mclk730.vMPLL_FUNC_CNTL = cpu_to_be32(mpll_func_cntl); 1898c2ecf20Sopenharmony_ci mclk->mclk730.vMPLL_FUNC_CNTL2 = cpu_to_be32(mpll_func_cntl_2); 1908c2ecf20Sopenharmony_ci mclk->mclk730.vMPLL_FUNC_CNTL3 = cpu_to_be32(mpll_func_cntl_3); 1918c2ecf20Sopenharmony_ci mclk->mclk730.vMPLL_SS = cpu_to_be32(mpll_ss); 1928c2ecf20Sopenharmony_ci mclk->mclk730.vMPLL_SS2 = cpu_to_be32(mpll_ss2); 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci return 0; 1958c2ecf20Sopenharmony_ci} 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_civoid rv730_read_clock_registers(struct radeon_device *rdev) 1988c2ecf20Sopenharmony_ci{ 1998c2ecf20Sopenharmony_ci struct rv7xx_power_info *pi = rv770_get_pi(rdev); 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci pi->clk_regs.rv730.cg_spll_func_cntl = 2028c2ecf20Sopenharmony_ci RREG32(CG_SPLL_FUNC_CNTL); 2038c2ecf20Sopenharmony_ci pi->clk_regs.rv730.cg_spll_func_cntl_2 = 2048c2ecf20Sopenharmony_ci RREG32(CG_SPLL_FUNC_CNTL_2); 2058c2ecf20Sopenharmony_ci pi->clk_regs.rv730.cg_spll_func_cntl_3 = 2068c2ecf20Sopenharmony_ci RREG32(CG_SPLL_FUNC_CNTL_3); 2078c2ecf20Sopenharmony_ci pi->clk_regs.rv730.cg_spll_spread_spectrum = 2088c2ecf20Sopenharmony_ci RREG32(CG_SPLL_SPREAD_SPECTRUM); 2098c2ecf20Sopenharmony_ci pi->clk_regs.rv730.cg_spll_spread_spectrum_2 = 2108c2ecf20Sopenharmony_ci RREG32(CG_SPLL_SPREAD_SPECTRUM_2); 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci pi->clk_regs.rv730.mclk_pwrmgt_cntl = 2138c2ecf20Sopenharmony_ci RREG32(TCI_MCLK_PWRMGT_CNTL); 2148c2ecf20Sopenharmony_ci pi->clk_regs.rv730.dll_cntl = 2158c2ecf20Sopenharmony_ci RREG32(TCI_DLL_CNTL); 2168c2ecf20Sopenharmony_ci pi->clk_regs.rv730.mpll_func_cntl = 2178c2ecf20Sopenharmony_ci RREG32(CG_MPLL_FUNC_CNTL); 2188c2ecf20Sopenharmony_ci pi->clk_regs.rv730.mpll_func_cntl2 = 2198c2ecf20Sopenharmony_ci RREG32(CG_MPLL_FUNC_CNTL_2); 2208c2ecf20Sopenharmony_ci pi->clk_regs.rv730.mpll_func_cntl3 = 2218c2ecf20Sopenharmony_ci RREG32(CG_MPLL_FUNC_CNTL_3); 2228c2ecf20Sopenharmony_ci pi->clk_regs.rv730.mpll_ss = 2238c2ecf20Sopenharmony_ci RREG32(CG_TCI_MPLL_SPREAD_SPECTRUM); 2248c2ecf20Sopenharmony_ci pi->clk_regs.rv730.mpll_ss2 = 2258c2ecf20Sopenharmony_ci RREG32(CG_TCI_MPLL_SPREAD_SPECTRUM_2); 2268c2ecf20Sopenharmony_ci} 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ciint rv730_populate_smc_acpi_state(struct radeon_device *rdev, 2298c2ecf20Sopenharmony_ci RV770_SMC_STATETABLE *table) 2308c2ecf20Sopenharmony_ci{ 2318c2ecf20Sopenharmony_ci struct rv7xx_power_info *pi = rv770_get_pi(rdev); 2328c2ecf20Sopenharmony_ci u32 mpll_func_cntl = 0; 2338c2ecf20Sopenharmony_ci u32 mpll_func_cntl_2 = 0 ; 2348c2ecf20Sopenharmony_ci u32 mpll_func_cntl_3 = 0; 2358c2ecf20Sopenharmony_ci u32 mclk_pwrmgt_cntl; 2368c2ecf20Sopenharmony_ci u32 dll_cntl; 2378c2ecf20Sopenharmony_ci u32 spll_func_cntl; 2388c2ecf20Sopenharmony_ci u32 spll_func_cntl_2; 2398c2ecf20Sopenharmony_ci u32 spll_func_cntl_3; 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci table->ACPIState = table->initialState; 2428c2ecf20Sopenharmony_ci table->ACPIState.flags &= ~PPSMC_SWSTATE_FLAG_DC; 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci if (pi->acpi_vddc) { 2458c2ecf20Sopenharmony_ci rv770_populate_vddc_value(rdev, pi->acpi_vddc, 2468c2ecf20Sopenharmony_ci &table->ACPIState.levels[0].vddc); 2478c2ecf20Sopenharmony_ci table->ACPIState.levels[0].gen2PCIE = pi->pcie_gen2 ? 2488c2ecf20Sopenharmony_ci pi->acpi_pcie_gen2 : 0; 2498c2ecf20Sopenharmony_ci table->ACPIState.levels[0].gen2XSP = 2508c2ecf20Sopenharmony_ci pi->acpi_pcie_gen2; 2518c2ecf20Sopenharmony_ci } else { 2528c2ecf20Sopenharmony_ci rv770_populate_vddc_value(rdev, pi->min_vddc_in_table, 2538c2ecf20Sopenharmony_ci &table->ACPIState.levels[0].vddc); 2548c2ecf20Sopenharmony_ci table->ACPIState.levels[0].gen2PCIE = 0; 2558c2ecf20Sopenharmony_ci } 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci mpll_func_cntl = pi->clk_regs.rv730.mpll_func_cntl; 2588c2ecf20Sopenharmony_ci mpll_func_cntl_2 = pi->clk_regs.rv730.mpll_func_cntl2; 2598c2ecf20Sopenharmony_ci mpll_func_cntl_3 = pi->clk_regs.rv730.mpll_func_cntl3; 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci mpll_func_cntl |= MPLL_RESET | MPLL_BYPASS_EN; 2628c2ecf20Sopenharmony_ci mpll_func_cntl &= ~MPLL_SLEEP; 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci mpll_func_cntl_2 &= ~MCLK_MUX_SEL_MASK; 2658c2ecf20Sopenharmony_ci mpll_func_cntl_2 |= MCLK_MUX_SEL(1); 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci mclk_pwrmgt_cntl = (MRDCKA_RESET | 2688c2ecf20Sopenharmony_ci MRDCKB_RESET | 2698c2ecf20Sopenharmony_ci MRDCKC_RESET | 2708c2ecf20Sopenharmony_ci MRDCKD_RESET | 2718c2ecf20Sopenharmony_ci MRDCKE_RESET | 2728c2ecf20Sopenharmony_ci MRDCKF_RESET | 2738c2ecf20Sopenharmony_ci MRDCKG_RESET | 2748c2ecf20Sopenharmony_ci MRDCKH_RESET | 2758c2ecf20Sopenharmony_ci MRDCKA_SLEEP | 2768c2ecf20Sopenharmony_ci MRDCKB_SLEEP | 2778c2ecf20Sopenharmony_ci MRDCKC_SLEEP | 2788c2ecf20Sopenharmony_ci MRDCKD_SLEEP | 2798c2ecf20Sopenharmony_ci MRDCKE_SLEEP | 2808c2ecf20Sopenharmony_ci MRDCKF_SLEEP | 2818c2ecf20Sopenharmony_ci MRDCKG_SLEEP | 2828c2ecf20Sopenharmony_ci MRDCKH_SLEEP); 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ci dll_cntl = 0xff000000; 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci spll_func_cntl = pi->clk_regs.rv730.cg_spll_func_cntl; 2878c2ecf20Sopenharmony_ci spll_func_cntl_2 = pi->clk_regs.rv730.cg_spll_func_cntl_2; 2888c2ecf20Sopenharmony_ci spll_func_cntl_3 = pi->clk_regs.rv730.cg_spll_func_cntl_3; 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci spll_func_cntl |= SPLL_RESET | SPLL_BYPASS_EN; 2918c2ecf20Sopenharmony_ci spll_func_cntl &= ~SPLL_SLEEP; 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci spll_func_cntl_2 &= ~SCLK_MUX_SEL_MASK; 2948c2ecf20Sopenharmony_ci spll_func_cntl_2 |= SCLK_MUX_SEL(4); 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_ci table->ACPIState.levels[0].mclk.mclk730.vMPLL_FUNC_CNTL = cpu_to_be32(mpll_func_cntl); 2978c2ecf20Sopenharmony_ci table->ACPIState.levels[0].mclk.mclk730.vMPLL_FUNC_CNTL2 = cpu_to_be32(mpll_func_cntl_2); 2988c2ecf20Sopenharmony_ci table->ACPIState.levels[0].mclk.mclk730.vMPLL_FUNC_CNTL3 = cpu_to_be32(mpll_func_cntl_3); 2998c2ecf20Sopenharmony_ci table->ACPIState.levels[0].mclk.mclk730.vMCLK_PWRMGT_CNTL = cpu_to_be32(mclk_pwrmgt_cntl); 3008c2ecf20Sopenharmony_ci table->ACPIState.levels[0].mclk.mclk730.vDLL_CNTL = cpu_to_be32(dll_cntl); 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci table->ACPIState.levels[0].mclk.mclk730.mclk_value = 0; 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci table->ACPIState.levels[0].sclk.vCG_SPLL_FUNC_CNTL = cpu_to_be32(spll_func_cntl); 3058c2ecf20Sopenharmony_ci table->ACPIState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_2 = cpu_to_be32(spll_func_cntl_2); 3068c2ecf20Sopenharmony_ci table->ACPIState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_3 = cpu_to_be32(spll_func_cntl_3); 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci table->ACPIState.levels[0].sclk.sclk_value = 0; 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci rv770_populate_mvdd_value(rdev, 0, &table->ACPIState.levels[0].mvdd); 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci table->ACPIState.levels[1] = table->ACPIState.levels[0]; 3138c2ecf20Sopenharmony_ci table->ACPIState.levels[2] = table->ACPIState.levels[0]; 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci return 0; 3168c2ecf20Sopenharmony_ci} 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ciint rv730_populate_smc_initial_state(struct radeon_device *rdev, 3198c2ecf20Sopenharmony_ci struct radeon_ps *radeon_state, 3208c2ecf20Sopenharmony_ci RV770_SMC_STATETABLE *table) 3218c2ecf20Sopenharmony_ci{ 3228c2ecf20Sopenharmony_ci struct rv7xx_ps *initial_state = rv770_get_ps(radeon_state); 3238c2ecf20Sopenharmony_ci struct rv7xx_power_info *pi = rv770_get_pi(rdev); 3248c2ecf20Sopenharmony_ci u32 a_t; 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci table->initialState.levels[0].mclk.mclk730.vMPLL_FUNC_CNTL = 3278c2ecf20Sopenharmony_ci cpu_to_be32(pi->clk_regs.rv730.mpll_func_cntl); 3288c2ecf20Sopenharmony_ci table->initialState.levels[0].mclk.mclk730.vMPLL_FUNC_CNTL2 = 3298c2ecf20Sopenharmony_ci cpu_to_be32(pi->clk_regs.rv730.mpll_func_cntl2); 3308c2ecf20Sopenharmony_ci table->initialState.levels[0].mclk.mclk730.vMPLL_FUNC_CNTL3 = 3318c2ecf20Sopenharmony_ci cpu_to_be32(pi->clk_regs.rv730.mpll_func_cntl3); 3328c2ecf20Sopenharmony_ci table->initialState.levels[0].mclk.mclk730.vMCLK_PWRMGT_CNTL = 3338c2ecf20Sopenharmony_ci cpu_to_be32(pi->clk_regs.rv730.mclk_pwrmgt_cntl); 3348c2ecf20Sopenharmony_ci table->initialState.levels[0].mclk.mclk730.vDLL_CNTL = 3358c2ecf20Sopenharmony_ci cpu_to_be32(pi->clk_regs.rv730.dll_cntl); 3368c2ecf20Sopenharmony_ci table->initialState.levels[0].mclk.mclk730.vMPLL_SS = 3378c2ecf20Sopenharmony_ci cpu_to_be32(pi->clk_regs.rv730.mpll_ss); 3388c2ecf20Sopenharmony_ci table->initialState.levels[0].mclk.mclk730.vMPLL_SS2 = 3398c2ecf20Sopenharmony_ci cpu_to_be32(pi->clk_regs.rv730.mpll_ss2); 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci table->initialState.levels[0].mclk.mclk730.mclk_value = 3428c2ecf20Sopenharmony_ci cpu_to_be32(initial_state->low.mclk); 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_ci table->initialState.levels[0].sclk.vCG_SPLL_FUNC_CNTL = 3458c2ecf20Sopenharmony_ci cpu_to_be32(pi->clk_regs.rv730.cg_spll_func_cntl); 3468c2ecf20Sopenharmony_ci table->initialState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_2 = 3478c2ecf20Sopenharmony_ci cpu_to_be32(pi->clk_regs.rv730.cg_spll_func_cntl_2); 3488c2ecf20Sopenharmony_ci table->initialState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_3 = 3498c2ecf20Sopenharmony_ci cpu_to_be32(pi->clk_regs.rv730.cg_spll_func_cntl_3); 3508c2ecf20Sopenharmony_ci table->initialState.levels[0].sclk.vCG_SPLL_SPREAD_SPECTRUM = 3518c2ecf20Sopenharmony_ci cpu_to_be32(pi->clk_regs.rv730.cg_spll_spread_spectrum); 3528c2ecf20Sopenharmony_ci table->initialState.levels[0].sclk.vCG_SPLL_SPREAD_SPECTRUM_2 = 3538c2ecf20Sopenharmony_ci cpu_to_be32(pi->clk_regs.rv730.cg_spll_spread_spectrum_2); 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_ci table->initialState.levels[0].sclk.sclk_value = 3568c2ecf20Sopenharmony_ci cpu_to_be32(initial_state->low.sclk); 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci table->initialState.levels[0].arbValue = MC_CG_ARB_FREQ_F0; 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_ci table->initialState.levels[0].seqValue = 3618c2ecf20Sopenharmony_ci rv770_get_seq_value(rdev, &initial_state->low); 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ci rv770_populate_vddc_value(rdev, 3648c2ecf20Sopenharmony_ci initial_state->low.vddc, 3658c2ecf20Sopenharmony_ci &table->initialState.levels[0].vddc); 3668c2ecf20Sopenharmony_ci rv770_populate_initial_mvdd_value(rdev, 3678c2ecf20Sopenharmony_ci &table->initialState.levels[0].mvdd); 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci a_t = CG_R(0xffff) | CG_L(0); 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_ci table->initialState.levels[0].aT = cpu_to_be32(a_t); 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci table->initialState.levels[0].bSP = cpu_to_be32(pi->dsp); 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_ci if (pi->boot_in_gen2) 3768c2ecf20Sopenharmony_ci table->initialState.levels[0].gen2PCIE = 1; 3778c2ecf20Sopenharmony_ci else 3788c2ecf20Sopenharmony_ci table->initialState.levels[0].gen2PCIE = 0; 3798c2ecf20Sopenharmony_ci if (initial_state->low.flags & ATOM_PPLIB_R600_FLAGS_PCIEGEN2) 3808c2ecf20Sopenharmony_ci table->initialState.levels[0].gen2XSP = 1; 3818c2ecf20Sopenharmony_ci else 3828c2ecf20Sopenharmony_ci table->initialState.levels[0].gen2XSP = 0; 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_ci table->initialState.levels[1] = table->initialState.levels[0]; 3858c2ecf20Sopenharmony_ci table->initialState.levels[2] = table->initialState.levels[0]; 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci table->initialState.flags |= PPSMC_SWSTATE_FLAG_DC; 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ci return 0; 3908c2ecf20Sopenharmony_ci} 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_civoid rv730_program_memory_timing_parameters(struct radeon_device *rdev, 3938c2ecf20Sopenharmony_ci struct radeon_ps *radeon_state) 3948c2ecf20Sopenharmony_ci{ 3958c2ecf20Sopenharmony_ci struct rv7xx_ps *state = rv770_get_ps(radeon_state); 3968c2ecf20Sopenharmony_ci u32 arb_refresh_rate = 0; 3978c2ecf20Sopenharmony_ci u32 dram_timing = 0; 3988c2ecf20Sopenharmony_ci u32 dram_timing2 = 0; 3998c2ecf20Sopenharmony_ci u32 old_dram_timing = 0; 4008c2ecf20Sopenharmony_ci u32 old_dram_timing2 = 0; 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_ci arb_refresh_rate = RREG32(MC_ARB_RFSH_RATE) & 4038c2ecf20Sopenharmony_ci ~(POWERMODE1_MASK | POWERMODE2_MASK | POWERMODE3_MASK); 4048c2ecf20Sopenharmony_ci arb_refresh_rate |= 4058c2ecf20Sopenharmony_ci (POWERMODE1(rv770_calculate_memory_refresh_rate(rdev, state->low.sclk)) | 4068c2ecf20Sopenharmony_ci POWERMODE2(rv770_calculate_memory_refresh_rate(rdev, state->medium.sclk)) | 4078c2ecf20Sopenharmony_ci POWERMODE3(rv770_calculate_memory_refresh_rate(rdev, state->high.sclk))); 4088c2ecf20Sopenharmony_ci WREG32(MC_ARB_RFSH_RATE, arb_refresh_rate); 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ci /* save the boot dram timings */ 4118c2ecf20Sopenharmony_ci old_dram_timing = RREG32(MC_ARB_DRAM_TIMING); 4128c2ecf20Sopenharmony_ci old_dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2); 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci radeon_atom_set_engine_dram_timings(rdev, 4158c2ecf20Sopenharmony_ci state->high.sclk, 4168c2ecf20Sopenharmony_ci state->high.mclk); 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_ci dram_timing = RREG32(MC_ARB_DRAM_TIMING); 4198c2ecf20Sopenharmony_ci dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2); 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_ci WREG32(MC_ARB_DRAM_TIMING_3, dram_timing); 4228c2ecf20Sopenharmony_ci WREG32(MC_ARB_DRAM_TIMING2_3, dram_timing2); 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_ci radeon_atom_set_engine_dram_timings(rdev, 4258c2ecf20Sopenharmony_ci state->medium.sclk, 4268c2ecf20Sopenharmony_ci state->medium.mclk); 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_ci dram_timing = RREG32(MC_ARB_DRAM_TIMING); 4298c2ecf20Sopenharmony_ci dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2); 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_ci WREG32(MC_ARB_DRAM_TIMING_2, dram_timing); 4328c2ecf20Sopenharmony_ci WREG32(MC_ARB_DRAM_TIMING2_2, dram_timing2); 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_ci radeon_atom_set_engine_dram_timings(rdev, 4358c2ecf20Sopenharmony_ci state->low.sclk, 4368c2ecf20Sopenharmony_ci state->low.mclk); 4378c2ecf20Sopenharmony_ci 4388c2ecf20Sopenharmony_ci dram_timing = RREG32(MC_ARB_DRAM_TIMING); 4398c2ecf20Sopenharmony_ci dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2); 4408c2ecf20Sopenharmony_ci 4418c2ecf20Sopenharmony_ci WREG32(MC_ARB_DRAM_TIMING_1, dram_timing); 4428c2ecf20Sopenharmony_ci WREG32(MC_ARB_DRAM_TIMING2_1, dram_timing2); 4438c2ecf20Sopenharmony_ci 4448c2ecf20Sopenharmony_ci /* restore the boot dram timings */ 4458c2ecf20Sopenharmony_ci WREG32(MC_ARB_DRAM_TIMING, old_dram_timing); 4468c2ecf20Sopenharmony_ci WREG32(MC_ARB_DRAM_TIMING2, old_dram_timing2); 4478c2ecf20Sopenharmony_ci 4488c2ecf20Sopenharmony_ci} 4498c2ecf20Sopenharmony_ci 4508c2ecf20Sopenharmony_civoid rv730_start_dpm(struct radeon_device *rdev) 4518c2ecf20Sopenharmony_ci{ 4528c2ecf20Sopenharmony_ci WREG32_P(SCLK_PWRMGT_CNTL, 0, ~SCLK_PWRMGT_OFF); 4538c2ecf20Sopenharmony_ci 4548c2ecf20Sopenharmony_ci WREG32_P(TCI_MCLK_PWRMGT_CNTL, 0, ~MPLL_PWRMGT_OFF); 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_ci WREG32_P(GENERAL_PWRMGT, GLOBAL_PWRMGT_EN, ~GLOBAL_PWRMGT_EN); 4578c2ecf20Sopenharmony_ci} 4588c2ecf20Sopenharmony_ci 4598c2ecf20Sopenharmony_civoid rv730_stop_dpm(struct radeon_device *rdev) 4608c2ecf20Sopenharmony_ci{ 4618c2ecf20Sopenharmony_ci PPSMC_Result result; 4628c2ecf20Sopenharmony_ci 4638c2ecf20Sopenharmony_ci result = rv770_send_msg_to_smc(rdev, PPSMC_MSG_TwoLevelsDisabled); 4648c2ecf20Sopenharmony_ci 4658c2ecf20Sopenharmony_ci if (result != PPSMC_Result_OK) 4668c2ecf20Sopenharmony_ci DRM_DEBUG("Could not force DPM to low\n"); 4678c2ecf20Sopenharmony_ci 4688c2ecf20Sopenharmony_ci WREG32_P(GENERAL_PWRMGT, 0, ~GLOBAL_PWRMGT_EN); 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_ci WREG32_P(SCLK_PWRMGT_CNTL, SCLK_PWRMGT_OFF, ~SCLK_PWRMGT_OFF); 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_ci WREG32_P(TCI_MCLK_PWRMGT_CNTL, MPLL_PWRMGT_OFF, ~MPLL_PWRMGT_OFF); 4738c2ecf20Sopenharmony_ci} 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_civoid rv730_program_dcodt(struct radeon_device *rdev, bool use_dcodt) 4768c2ecf20Sopenharmony_ci{ 4778c2ecf20Sopenharmony_ci struct rv7xx_power_info *pi = rv770_get_pi(rdev); 4788c2ecf20Sopenharmony_ci u32 i = use_dcodt ? 0 : 1; 4798c2ecf20Sopenharmony_ci u32 mc4_io_pad_cntl; 4808c2ecf20Sopenharmony_ci 4818c2ecf20Sopenharmony_ci mc4_io_pad_cntl = RREG32(MC4_IO_DQ_PAD_CNTL_D0_I0); 4828c2ecf20Sopenharmony_ci mc4_io_pad_cntl &= 0xFFFFFF00; 4838c2ecf20Sopenharmony_ci mc4_io_pad_cntl |= pi->odt_value_0[i]; 4848c2ecf20Sopenharmony_ci WREG32(MC4_IO_DQ_PAD_CNTL_D0_I0, mc4_io_pad_cntl); 4858c2ecf20Sopenharmony_ci WREG32(MC4_IO_DQ_PAD_CNTL_D0_I1, mc4_io_pad_cntl); 4868c2ecf20Sopenharmony_ci 4878c2ecf20Sopenharmony_ci mc4_io_pad_cntl = RREG32(MC4_IO_QS_PAD_CNTL_D0_I0); 4888c2ecf20Sopenharmony_ci mc4_io_pad_cntl &= 0xFFFFFF00; 4898c2ecf20Sopenharmony_ci mc4_io_pad_cntl |= pi->odt_value_1[i]; 4908c2ecf20Sopenharmony_ci WREG32(MC4_IO_QS_PAD_CNTL_D0_I0, mc4_io_pad_cntl); 4918c2ecf20Sopenharmony_ci WREG32(MC4_IO_QS_PAD_CNTL_D0_I1, mc4_io_pad_cntl); 4928c2ecf20Sopenharmony_ci} 4938c2ecf20Sopenharmony_ci 4948c2ecf20Sopenharmony_civoid rv730_get_odt_values(struct radeon_device *rdev) 4958c2ecf20Sopenharmony_ci{ 4968c2ecf20Sopenharmony_ci struct rv7xx_power_info *pi = rv770_get_pi(rdev); 4978c2ecf20Sopenharmony_ci u32 mc4_io_pad_cntl; 4988c2ecf20Sopenharmony_ci 4998c2ecf20Sopenharmony_ci pi->odt_value_0[0] = (u8)0; 5008c2ecf20Sopenharmony_ci pi->odt_value_1[0] = (u8)0x80; 5018c2ecf20Sopenharmony_ci 5028c2ecf20Sopenharmony_ci mc4_io_pad_cntl = RREG32(MC4_IO_DQ_PAD_CNTL_D0_I0); 5038c2ecf20Sopenharmony_ci pi->odt_value_0[1] = (u8)(mc4_io_pad_cntl & 0xff); 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci mc4_io_pad_cntl = RREG32(MC4_IO_QS_PAD_CNTL_D0_I0); 5068c2ecf20Sopenharmony_ci pi->odt_value_1[1] = (u8)(mc4_io_pad_cntl & 0xff); 5078c2ecf20Sopenharmony_ci} 508