18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright 2012 Advanced Micro Devices, Inc. 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 58c2ecf20Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 68c2ecf20Sopenharmony_ci * to deal in the Software without restriction, including without limitation 78c2ecf20Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 88c2ecf20Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 98c2ecf20Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * The above copyright notice and this permission notice shall be included in 128c2ecf20Sopenharmony_ci * all copies or substantial portions of the Software. 138c2ecf20Sopenharmony_ci * 148c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 158c2ecf20Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 168c2ecf20Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 178c2ecf20Sopenharmony_ci * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 188c2ecf20Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 198c2ecf20Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 208c2ecf20Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE. 218c2ecf20Sopenharmony_ci * 228c2ecf20Sopenharmony_ci */ 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#include "radeon.h" 258c2ecf20Sopenharmony_ci#include "radeon_asic.h" 268c2ecf20Sopenharmony_ci#include "sumod.h" 278c2ecf20Sopenharmony_ci#include "r600_dpm.h" 288c2ecf20Sopenharmony_ci#include "cypress_dpm.h" 298c2ecf20Sopenharmony_ci#include "sumo_dpm.h" 308c2ecf20Sopenharmony_ci#include <linux/seq_file.h> 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci#define SUMO_MAX_DEEPSLEEP_DIVIDER_ID 5 338c2ecf20Sopenharmony_ci#define SUMO_MINIMUM_ENGINE_CLOCK 800 348c2ecf20Sopenharmony_ci#define BOOST_DPM_LEVEL 7 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_cistatic const u32 sumo_utc[SUMO_PM_NUMBER_OF_TC] = 378c2ecf20Sopenharmony_ci{ 388c2ecf20Sopenharmony_ci SUMO_UTC_DFLT_00, 398c2ecf20Sopenharmony_ci SUMO_UTC_DFLT_01, 408c2ecf20Sopenharmony_ci SUMO_UTC_DFLT_02, 418c2ecf20Sopenharmony_ci SUMO_UTC_DFLT_03, 428c2ecf20Sopenharmony_ci SUMO_UTC_DFLT_04, 438c2ecf20Sopenharmony_ci SUMO_UTC_DFLT_05, 448c2ecf20Sopenharmony_ci SUMO_UTC_DFLT_06, 458c2ecf20Sopenharmony_ci SUMO_UTC_DFLT_07, 468c2ecf20Sopenharmony_ci SUMO_UTC_DFLT_08, 478c2ecf20Sopenharmony_ci SUMO_UTC_DFLT_09, 488c2ecf20Sopenharmony_ci SUMO_UTC_DFLT_10, 498c2ecf20Sopenharmony_ci SUMO_UTC_DFLT_11, 508c2ecf20Sopenharmony_ci SUMO_UTC_DFLT_12, 518c2ecf20Sopenharmony_ci SUMO_UTC_DFLT_13, 528c2ecf20Sopenharmony_ci SUMO_UTC_DFLT_14, 538c2ecf20Sopenharmony_ci}; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_cistatic const u32 sumo_dtc[SUMO_PM_NUMBER_OF_TC] = 568c2ecf20Sopenharmony_ci{ 578c2ecf20Sopenharmony_ci SUMO_DTC_DFLT_00, 588c2ecf20Sopenharmony_ci SUMO_DTC_DFLT_01, 598c2ecf20Sopenharmony_ci SUMO_DTC_DFLT_02, 608c2ecf20Sopenharmony_ci SUMO_DTC_DFLT_03, 618c2ecf20Sopenharmony_ci SUMO_DTC_DFLT_04, 628c2ecf20Sopenharmony_ci SUMO_DTC_DFLT_05, 638c2ecf20Sopenharmony_ci SUMO_DTC_DFLT_06, 648c2ecf20Sopenharmony_ci SUMO_DTC_DFLT_07, 658c2ecf20Sopenharmony_ci SUMO_DTC_DFLT_08, 668c2ecf20Sopenharmony_ci SUMO_DTC_DFLT_09, 678c2ecf20Sopenharmony_ci SUMO_DTC_DFLT_10, 688c2ecf20Sopenharmony_ci SUMO_DTC_DFLT_11, 698c2ecf20Sopenharmony_ci SUMO_DTC_DFLT_12, 708c2ecf20Sopenharmony_ci SUMO_DTC_DFLT_13, 718c2ecf20Sopenharmony_ci SUMO_DTC_DFLT_14, 728c2ecf20Sopenharmony_ci}; 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_cistatic struct sumo_ps *sumo_get_ps(struct radeon_ps *rps) 758c2ecf20Sopenharmony_ci{ 768c2ecf20Sopenharmony_ci struct sumo_ps *ps = rps->ps_priv; 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci return ps; 798c2ecf20Sopenharmony_ci} 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_cistruct sumo_power_info *sumo_get_pi(struct radeon_device *rdev) 828c2ecf20Sopenharmony_ci{ 838c2ecf20Sopenharmony_ci struct sumo_power_info *pi = rdev->pm.dpm.priv; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci return pi; 868c2ecf20Sopenharmony_ci} 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_cistatic void sumo_gfx_clockgating_enable(struct radeon_device *rdev, bool enable) 898c2ecf20Sopenharmony_ci{ 908c2ecf20Sopenharmony_ci if (enable) 918c2ecf20Sopenharmony_ci WREG32_P(SCLK_PWRMGT_CNTL, DYN_GFX_CLK_OFF_EN, ~DYN_GFX_CLK_OFF_EN); 928c2ecf20Sopenharmony_ci else { 938c2ecf20Sopenharmony_ci WREG32_P(SCLK_PWRMGT_CNTL, 0, ~DYN_GFX_CLK_OFF_EN); 948c2ecf20Sopenharmony_ci WREG32_P(SCLK_PWRMGT_CNTL, GFX_CLK_FORCE_ON, ~GFX_CLK_FORCE_ON); 958c2ecf20Sopenharmony_ci WREG32_P(SCLK_PWRMGT_CNTL, 0, ~GFX_CLK_FORCE_ON); 968c2ecf20Sopenharmony_ci RREG32(GB_ADDR_CONFIG); 978c2ecf20Sopenharmony_ci } 988c2ecf20Sopenharmony_ci} 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci#define CGCG_CGTT_LOCAL0_MASK 0xE5BFFFFF 1018c2ecf20Sopenharmony_ci#define CGCG_CGTT_LOCAL1_MASK 0xEFFF07FF 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_cistatic void sumo_mg_clockgating_enable(struct radeon_device *rdev, bool enable) 1048c2ecf20Sopenharmony_ci{ 1058c2ecf20Sopenharmony_ci u32 local0; 1068c2ecf20Sopenharmony_ci u32 local1; 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci local0 = RREG32(CG_CGTT_LOCAL_0); 1098c2ecf20Sopenharmony_ci local1 = RREG32(CG_CGTT_LOCAL_1); 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci if (enable) { 1128c2ecf20Sopenharmony_ci WREG32(CG_CGTT_LOCAL_0, (0 & CGCG_CGTT_LOCAL0_MASK) | (local0 & ~CGCG_CGTT_LOCAL0_MASK) ); 1138c2ecf20Sopenharmony_ci WREG32(CG_CGTT_LOCAL_1, (0 & CGCG_CGTT_LOCAL1_MASK) | (local1 & ~CGCG_CGTT_LOCAL1_MASK) ); 1148c2ecf20Sopenharmony_ci } else { 1158c2ecf20Sopenharmony_ci WREG32(CG_CGTT_LOCAL_0, (0xFFFFFFFF & CGCG_CGTT_LOCAL0_MASK) | (local0 & ~CGCG_CGTT_LOCAL0_MASK) ); 1168c2ecf20Sopenharmony_ci WREG32(CG_CGTT_LOCAL_1, (0xFFFFCFFF & CGCG_CGTT_LOCAL1_MASK) | (local1 & ~CGCG_CGTT_LOCAL1_MASK) ); 1178c2ecf20Sopenharmony_ci } 1188c2ecf20Sopenharmony_ci} 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_cistatic void sumo_program_git(struct radeon_device *rdev) 1218c2ecf20Sopenharmony_ci{ 1228c2ecf20Sopenharmony_ci u32 p, u; 1238c2ecf20Sopenharmony_ci u32 xclk = radeon_get_xclk(rdev); 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci r600_calculate_u_and_p(SUMO_GICST_DFLT, 1268c2ecf20Sopenharmony_ci xclk, 16, &p, &u); 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci WREG32_P(CG_GIT, CG_GICST(p), ~CG_GICST_MASK); 1298c2ecf20Sopenharmony_ci} 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_cistatic void sumo_program_grsd(struct radeon_device *rdev) 1328c2ecf20Sopenharmony_ci{ 1338c2ecf20Sopenharmony_ci u32 p, u; 1348c2ecf20Sopenharmony_ci u32 xclk = radeon_get_xclk(rdev); 1358c2ecf20Sopenharmony_ci u32 grs = 256 * 25 / 100; 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci r600_calculate_u_and_p(1, xclk, 14, &p, &u); 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci WREG32(CG_GCOOR, PHC(grs) | SDC(p) | SU(u)); 1408c2ecf20Sopenharmony_ci} 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_civoid sumo_gfx_clockgating_initialize(struct radeon_device *rdev) 1438c2ecf20Sopenharmony_ci{ 1448c2ecf20Sopenharmony_ci sumo_program_git(rdev); 1458c2ecf20Sopenharmony_ci sumo_program_grsd(rdev); 1468c2ecf20Sopenharmony_ci} 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_cistatic void sumo_gfx_powergating_initialize(struct radeon_device *rdev) 1498c2ecf20Sopenharmony_ci{ 1508c2ecf20Sopenharmony_ci u32 rcu_pwr_gating_cntl; 1518c2ecf20Sopenharmony_ci u32 p, u; 1528c2ecf20Sopenharmony_ci u32 p_c, p_p, d_p; 1538c2ecf20Sopenharmony_ci u32 r_t, i_t; 1548c2ecf20Sopenharmony_ci u32 xclk = radeon_get_xclk(rdev); 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci if (rdev->family == CHIP_PALM) { 1578c2ecf20Sopenharmony_ci p_c = 4; 1588c2ecf20Sopenharmony_ci d_p = 10; 1598c2ecf20Sopenharmony_ci r_t = 10; 1608c2ecf20Sopenharmony_ci i_t = 4; 1618c2ecf20Sopenharmony_ci p_p = 50 + 1000/200 + 6 * 32; 1628c2ecf20Sopenharmony_ci } else { 1638c2ecf20Sopenharmony_ci p_c = 16; 1648c2ecf20Sopenharmony_ci d_p = 50; 1658c2ecf20Sopenharmony_ci r_t = 50; 1668c2ecf20Sopenharmony_ci i_t = 50; 1678c2ecf20Sopenharmony_ci p_p = 113; 1688c2ecf20Sopenharmony_ci } 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci WREG32(CG_SCRATCH2, 0x01B60A17); 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci r600_calculate_u_and_p(SUMO_GFXPOWERGATINGT_DFLT, 1738c2ecf20Sopenharmony_ci xclk, 16, &p, &u); 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci WREG32_P(CG_PWR_GATING_CNTL, PGP(p) | PGU(u), 1768c2ecf20Sopenharmony_ci ~(PGP_MASK | PGU_MASK)); 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci r600_calculate_u_and_p(SUMO_VOLTAGEDROPT_DFLT, 1798c2ecf20Sopenharmony_ci xclk, 16, &p, &u); 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci WREG32_P(CG_CG_VOLTAGE_CNTL, PGP(p) | PGU(u), 1828c2ecf20Sopenharmony_ci ~(PGP_MASK | PGU_MASK)); 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci if (rdev->family == CHIP_PALM) { 1858c2ecf20Sopenharmony_ci WREG32_RCU(RCU_PWR_GATING_SEQ0, 0x10103210); 1868c2ecf20Sopenharmony_ci WREG32_RCU(RCU_PWR_GATING_SEQ1, 0x10101010); 1878c2ecf20Sopenharmony_ci } else { 1888c2ecf20Sopenharmony_ci WREG32_RCU(RCU_PWR_GATING_SEQ0, 0x76543210); 1898c2ecf20Sopenharmony_ci WREG32_RCU(RCU_PWR_GATING_SEQ1, 0xFEDCBA98); 1908c2ecf20Sopenharmony_ci } 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci rcu_pwr_gating_cntl = RREG32_RCU(RCU_PWR_GATING_CNTL); 1938c2ecf20Sopenharmony_ci rcu_pwr_gating_cntl &= 1948c2ecf20Sopenharmony_ci ~(RSVD_MASK | PCV_MASK | PGS_MASK); 1958c2ecf20Sopenharmony_ci rcu_pwr_gating_cntl |= PCV(p_c) | PGS(1) | PWR_GATING_EN; 1968c2ecf20Sopenharmony_ci if (rdev->family == CHIP_PALM) { 1978c2ecf20Sopenharmony_ci rcu_pwr_gating_cntl &= ~PCP_MASK; 1988c2ecf20Sopenharmony_ci rcu_pwr_gating_cntl |= PCP(0x77); 1998c2ecf20Sopenharmony_ci } 2008c2ecf20Sopenharmony_ci WREG32_RCU(RCU_PWR_GATING_CNTL, rcu_pwr_gating_cntl); 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci rcu_pwr_gating_cntl = RREG32_RCU(RCU_PWR_GATING_CNTL_2); 2038c2ecf20Sopenharmony_ci rcu_pwr_gating_cntl &= ~(MPPU_MASK | MPPD_MASK); 2048c2ecf20Sopenharmony_ci rcu_pwr_gating_cntl |= MPPU(p_p) | MPPD(50); 2058c2ecf20Sopenharmony_ci WREG32_RCU(RCU_PWR_GATING_CNTL_2, rcu_pwr_gating_cntl); 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci rcu_pwr_gating_cntl = RREG32_RCU(RCU_PWR_GATING_CNTL_3); 2088c2ecf20Sopenharmony_ci rcu_pwr_gating_cntl &= ~(DPPU_MASK | DPPD_MASK); 2098c2ecf20Sopenharmony_ci rcu_pwr_gating_cntl |= DPPU(d_p) | DPPD(50); 2108c2ecf20Sopenharmony_ci WREG32_RCU(RCU_PWR_GATING_CNTL_3, rcu_pwr_gating_cntl); 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci rcu_pwr_gating_cntl = RREG32_RCU(RCU_PWR_GATING_CNTL_4); 2138c2ecf20Sopenharmony_ci rcu_pwr_gating_cntl &= ~(RT_MASK | IT_MASK); 2148c2ecf20Sopenharmony_ci rcu_pwr_gating_cntl |= RT(r_t) | IT(i_t); 2158c2ecf20Sopenharmony_ci WREG32_RCU(RCU_PWR_GATING_CNTL_4, rcu_pwr_gating_cntl); 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci if (rdev->family == CHIP_PALM) 2188c2ecf20Sopenharmony_ci WREG32_RCU(RCU_PWR_GATING_CNTL_5, 0xA02); 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci sumo_smu_pg_init(rdev); 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci rcu_pwr_gating_cntl = RREG32_RCU(RCU_PWR_GATING_CNTL); 2238c2ecf20Sopenharmony_ci rcu_pwr_gating_cntl &= 2248c2ecf20Sopenharmony_ci ~(RSVD_MASK | PCV_MASK | PGS_MASK); 2258c2ecf20Sopenharmony_ci rcu_pwr_gating_cntl |= PCV(p_c) | PGS(4) | PWR_GATING_EN; 2268c2ecf20Sopenharmony_ci if (rdev->family == CHIP_PALM) { 2278c2ecf20Sopenharmony_ci rcu_pwr_gating_cntl &= ~PCP_MASK; 2288c2ecf20Sopenharmony_ci rcu_pwr_gating_cntl |= PCP(0x77); 2298c2ecf20Sopenharmony_ci } 2308c2ecf20Sopenharmony_ci WREG32_RCU(RCU_PWR_GATING_CNTL, rcu_pwr_gating_cntl); 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci if (rdev->family == CHIP_PALM) { 2338c2ecf20Sopenharmony_ci rcu_pwr_gating_cntl = RREG32_RCU(RCU_PWR_GATING_CNTL_2); 2348c2ecf20Sopenharmony_ci rcu_pwr_gating_cntl &= ~(MPPU_MASK | MPPD_MASK); 2358c2ecf20Sopenharmony_ci rcu_pwr_gating_cntl |= MPPU(113) | MPPD(50); 2368c2ecf20Sopenharmony_ci WREG32_RCU(RCU_PWR_GATING_CNTL_2, rcu_pwr_gating_cntl); 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci rcu_pwr_gating_cntl = RREG32_RCU(RCU_PWR_GATING_CNTL_3); 2398c2ecf20Sopenharmony_ci rcu_pwr_gating_cntl &= ~(DPPU_MASK | DPPD_MASK); 2408c2ecf20Sopenharmony_ci rcu_pwr_gating_cntl |= DPPU(16) | DPPD(50); 2418c2ecf20Sopenharmony_ci WREG32_RCU(RCU_PWR_GATING_CNTL_3, rcu_pwr_gating_cntl); 2428c2ecf20Sopenharmony_ci } 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci sumo_smu_pg_init(rdev); 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci rcu_pwr_gating_cntl = RREG32_RCU(RCU_PWR_GATING_CNTL); 2478c2ecf20Sopenharmony_ci rcu_pwr_gating_cntl &= 2488c2ecf20Sopenharmony_ci ~(RSVD_MASK | PCV_MASK | PGS_MASK); 2498c2ecf20Sopenharmony_ci rcu_pwr_gating_cntl |= PGS(5) | PWR_GATING_EN; 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci if (rdev->family == CHIP_PALM) { 2528c2ecf20Sopenharmony_ci rcu_pwr_gating_cntl |= PCV(4); 2538c2ecf20Sopenharmony_ci rcu_pwr_gating_cntl &= ~PCP_MASK; 2548c2ecf20Sopenharmony_ci rcu_pwr_gating_cntl |= PCP(0x77); 2558c2ecf20Sopenharmony_ci } else 2568c2ecf20Sopenharmony_ci rcu_pwr_gating_cntl |= PCV(11); 2578c2ecf20Sopenharmony_ci WREG32_RCU(RCU_PWR_GATING_CNTL, rcu_pwr_gating_cntl); 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ci if (rdev->family == CHIP_PALM) { 2608c2ecf20Sopenharmony_ci rcu_pwr_gating_cntl = RREG32_RCU(RCU_PWR_GATING_CNTL_2); 2618c2ecf20Sopenharmony_ci rcu_pwr_gating_cntl &= ~(MPPU_MASK | MPPD_MASK); 2628c2ecf20Sopenharmony_ci rcu_pwr_gating_cntl |= MPPU(113) | MPPD(50); 2638c2ecf20Sopenharmony_ci WREG32_RCU(RCU_PWR_GATING_CNTL_2, rcu_pwr_gating_cntl); 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ci rcu_pwr_gating_cntl = RREG32_RCU(RCU_PWR_GATING_CNTL_3); 2668c2ecf20Sopenharmony_ci rcu_pwr_gating_cntl &= ~(DPPU_MASK | DPPD_MASK); 2678c2ecf20Sopenharmony_ci rcu_pwr_gating_cntl |= DPPU(22) | DPPD(50); 2688c2ecf20Sopenharmony_ci WREG32_RCU(RCU_PWR_GATING_CNTL_3, rcu_pwr_gating_cntl); 2698c2ecf20Sopenharmony_ci } 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci sumo_smu_pg_init(rdev); 2728c2ecf20Sopenharmony_ci} 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_cistatic void sumo_gfx_powergating_enable(struct radeon_device *rdev, bool enable) 2758c2ecf20Sopenharmony_ci{ 2768c2ecf20Sopenharmony_ci if (enable) 2778c2ecf20Sopenharmony_ci WREG32_P(CG_PWR_GATING_CNTL, DYN_PWR_DOWN_EN, ~DYN_PWR_DOWN_EN); 2788c2ecf20Sopenharmony_ci else { 2798c2ecf20Sopenharmony_ci WREG32_P(CG_PWR_GATING_CNTL, 0, ~DYN_PWR_DOWN_EN); 2808c2ecf20Sopenharmony_ci RREG32(GB_ADDR_CONFIG); 2818c2ecf20Sopenharmony_ci } 2828c2ecf20Sopenharmony_ci} 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_cistatic int sumo_enable_clock_power_gating(struct radeon_device *rdev) 2858c2ecf20Sopenharmony_ci{ 2868c2ecf20Sopenharmony_ci struct sumo_power_info *pi = sumo_get_pi(rdev); 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ci if (pi->enable_gfx_clock_gating) 2898c2ecf20Sopenharmony_ci sumo_gfx_clockgating_initialize(rdev); 2908c2ecf20Sopenharmony_ci if (pi->enable_gfx_power_gating) 2918c2ecf20Sopenharmony_ci sumo_gfx_powergating_initialize(rdev); 2928c2ecf20Sopenharmony_ci if (pi->enable_mg_clock_gating) 2938c2ecf20Sopenharmony_ci sumo_mg_clockgating_enable(rdev, true); 2948c2ecf20Sopenharmony_ci if (pi->enable_gfx_clock_gating) 2958c2ecf20Sopenharmony_ci sumo_gfx_clockgating_enable(rdev, true); 2968c2ecf20Sopenharmony_ci if (pi->enable_gfx_power_gating) 2978c2ecf20Sopenharmony_ci sumo_gfx_powergating_enable(rdev, true); 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci return 0; 3008c2ecf20Sopenharmony_ci} 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_cistatic void sumo_disable_clock_power_gating(struct radeon_device *rdev) 3038c2ecf20Sopenharmony_ci{ 3048c2ecf20Sopenharmony_ci struct sumo_power_info *pi = sumo_get_pi(rdev); 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_ci if (pi->enable_gfx_clock_gating) 3078c2ecf20Sopenharmony_ci sumo_gfx_clockgating_enable(rdev, false); 3088c2ecf20Sopenharmony_ci if (pi->enable_gfx_power_gating) 3098c2ecf20Sopenharmony_ci sumo_gfx_powergating_enable(rdev, false); 3108c2ecf20Sopenharmony_ci if (pi->enable_mg_clock_gating) 3118c2ecf20Sopenharmony_ci sumo_mg_clockgating_enable(rdev, false); 3128c2ecf20Sopenharmony_ci} 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_cistatic void sumo_calculate_bsp(struct radeon_device *rdev, 3158c2ecf20Sopenharmony_ci u32 high_clk) 3168c2ecf20Sopenharmony_ci{ 3178c2ecf20Sopenharmony_ci struct sumo_power_info *pi = sumo_get_pi(rdev); 3188c2ecf20Sopenharmony_ci u32 xclk = radeon_get_xclk(rdev); 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_ci pi->pasi = 65535 * 100 / high_clk; 3218c2ecf20Sopenharmony_ci pi->asi = 65535 * 100 / high_clk; 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ci r600_calculate_u_and_p(pi->asi, 3248c2ecf20Sopenharmony_ci xclk, 16, &pi->bsp, &pi->bsu); 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci r600_calculate_u_and_p(pi->pasi, 3278c2ecf20Sopenharmony_ci xclk, 16, &pi->pbsp, &pi->pbsu); 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ci pi->dsp = BSP(pi->bsp) | BSU(pi->bsu); 3308c2ecf20Sopenharmony_ci pi->psp = BSP(pi->pbsp) | BSU(pi->pbsu); 3318c2ecf20Sopenharmony_ci} 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_cistatic void sumo_init_bsp(struct radeon_device *rdev) 3348c2ecf20Sopenharmony_ci{ 3358c2ecf20Sopenharmony_ci struct sumo_power_info *pi = sumo_get_pi(rdev); 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci WREG32(CG_BSP_0, pi->psp); 3388c2ecf20Sopenharmony_ci} 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_cistatic void sumo_program_bsp(struct radeon_device *rdev, 3428c2ecf20Sopenharmony_ci struct radeon_ps *rps) 3438c2ecf20Sopenharmony_ci{ 3448c2ecf20Sopenharmony_ci struct sumo_power_info *pi = sumo_get_pi(rdev); 3458c2ecf20Sopenharmony_ci struct sumo_ps *ps = sumo_get_ps(rps); 3468c2ecf20Sopenharmony_ci u32 i; 3478c2ecf20Sopenharmony_ci u32 highest_engine_clock = ps->levels[ps->num_levels - 1].sclk; 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci if (ps->flags & SUMO_POWERSTATE_FLAGS_BOOST_STATE) 3508c2ecf20Sopenharmony_ci highest_engine_clock = pi->boost_pl.sclk; 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci sumo_calculate_bsp(rdev, highest_engine_clock); 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_ci for (i = 0; i < ps->num_levels - 1; i++) 3558c2ecf20Sopenharmony_ci WREG32(CG_BSP_0 + (i * 4), pi->dsp); 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_ci WREG32(CG_BSP_0 + (i * 4), pi->psp); 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ci if (ps->flags & SUMO_POWERSTATE_FLAGS_BOOST_STATE) 3608c2ecf20Sopenharmony_ci WREG32(CG_BSP_0 + (BOOST_DPM_LEVEL * 4), pi->psp); 3618c2ecf20Sopenharmony_ci} 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_cistatic void sumo_write_at(struct radeon_device *rdev, 3648c2ecf20Sopenharmony_ci u32 index, u32 value) 3658c2ecf20Sopenharmony_ci{ 3668c2ecf20Sopenharmony_ci if (index == 0) 3678c2ecf20Sopenharmony_ci WREG32(CG_AT_0, value); 3688c2ecf20Sopenharmony_ci else if (index == 1) 3698c2ecf20Sopenharmony_ci WREG32(CG_AT_1, value); 3708c2ecf20Sopenharmony_ci else if (index == 2) 3718c2ecf20Sopenharmony_ci WREG32(CG_AT_2, value); 3728c2ecf20Sopenharmony_ci else if (index == 3) 3738c2ecf20Sopenharmony_ci WREG32(CG_AT_3, value); 3748c2ecf20Sopenharmony_ci else if (index == 4) 3758c2ecf20Sopenharmony_ci WREG32(CG_AT_4, value); 3768c2ecf20Sopenharmony_ci else if (index == 5) 3778c2ecf20Sopenharmony_ci WREG32(CG_AT_5, value); 3788c2ecf20Sopenharmony_ci else if (index == 6) 3798c2ecf20Sopenharmony_ci WREG32(CG_AT_6, value); 3808c2ecf20Sopenharmony_ci else if (index == 7) 3818c2ecf20Sopenharmony_ci WREG32(CG_AT_7, value); 3828c2ecf20Sopenharmony_ci} 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_cistatic void sumo_program_at(struct radeon_device *rdev, 3858c2ecf20Sopenharmony_ci struct radeon_ps *rps) 3868c2ecf20Sopenharmony_ci{ 3878c2ecf20Sopenharmony_ci struct sumo_power_info *pi = sumo_get_pi(rdev); 3888c2ecf20Sopenharmony_ci struct sumo_ps *ps = sumo_get_ps(rps); 3898c2ecf20Sopenharmony_ci u32 asi; 3908c2ecf20Sopenharmony_ci u32 i; 3918c2ecf20Sopenharmony_ci u32 m_a; 3928c2ecf20Sopenharmony_ci u32 a_t; 3938c2ecf20Sopenharmony_ci u32 r[SUMO_MAX_HARDWARE_POWERLEVELS]; 3948c2ecf20Sopenharmony_ci u32 l[SUMO_MAX_HARDWARE_POWERLEVELS]; 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_ci r[0] = SUMO_R_DFLT0; 3978c2ecf20Sopenharmony_ci r[1] = SUMO_R_DFLT1; 3988c2ecf20Sopenharmony_ci r[2] = SUMO_R_DFLT2; 3998c2ecf20Sopenharmony_ci r[3] = SUMO_R_DFLT3; 4008c2ecf20Sopenharmony_ci r[4] = SUMO_R_DFLT4; 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_ci l[0] = SUMO_L_DFLT0; 4038c2ecf20Sopenharmony_ci l[1] = SUMO_L_DFLT1; 4048c2ecf20Sopenharmony_ci l[2] = SUMO_L_DFLT2; 4058c2ecf20Sopenharmony_ci l[3] = SUMO_L_DFLT3; 4068c2ecf20Sopenharmony_ci l[4] = SUMO_L_DFLT4; 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_ci for (i = 0; i < ps->num_levels; i++) { 4098c2ecf20Sopenharmony_ci asi = (i == ps->num_levels - 1) ? pi->pasi : pi->asi; 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci m_a = asi * ps->levels[i].sclk / 100; 4128c2ecf20Sopenharmony_ci 4138c2ecf20Sopenharmony_ci a_t = CG_R(m_a * r[i] / 100) | CG_L(m_a * l[i] / 100); 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_ci sumo_write_at(rdev, i, a_t); 4168c2ecf20Sopenharmony_ci } 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_ci if (ps->flags & SUMO_POWERSTATE_FLAGS_BOOST_STATE) { 4198c2ecf20Sopenharmony_ci asi = pi->pasi; 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_ci m_a = asi * pi->boost_pl.sclk / 100; 4228c2ecf20Sopenharmony_ci 4238c2ecf20Sopenharmony_ci a_t = CG_R(m_a * r[ps->num_levels - 1] / 100) | 4248c2ecf20Sopenharmony_ci CG_L(m_a * l[ps->num_levels - 1] / 100); 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_ci sumo_write_at(rdev, BOOST_DPM_LEVEL, a_t); 4278c2ecf20Sopenharmony_ci } 4288c2ecf20Sopenharmony_ci} 4298c2ecf20Sopenharmony_ci 4308c2ecf20Sopenharmony_cistatic void sumo_program_tp(struct radeon_device *rdev) 4318c2ecf20Sopenharmony_ci{ 4328c2ecf20Sopenharmony_ci int i; 4338c2ecf20Sopenharmony_ci enum r600_td td = R600_TD_DFLT; 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_ci for (i = 0; i < SUMO_PM_NUMBER_OF_TC; i++) { 4368c2ecf20Sopenharmony_ci WREG32_P(CG_FFCT_0 + (i * 4), UTC_0(sumo_utc[i]), ~UTC_0_MASK); 4378c2ecf20Sopenharmony_ci WREG32_P(CG_FFCT_0 + (i * 4), DTC_0(sumo_dtc[i]), ~DTC_0_MASK); 4388c2ecf20Sopenharmony_ci } 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_ci if (td == R600_TD_AUTO) 4418c2ecf20Sopenharmony_ci WREG32_P(SCLK_PWRMGT_CNTL, 0, ~FIR_FORCE_TREND_SEL); 4428c2ecf20Sopenharmony_ci else 4438c2ecf20Sopenharmony_ci WREG32_P(SCLK_PWRMGT_CNTL, FIR_FORCE_TREND_SEL, ~FIR_FORCE_TREND_SEL); 4448c2ecf20Sopenharmony_ci 4458c2ecf20Sopenharmony_ci if (td == R600_TD_UP) 4468c2ecf20Sopenharmony_ci WREG32_P(SCLK_PWRMGT_CNTL, 0, ~FIR_TREND_MODE); 4478c2ecf20Sopenharmony_ci 4488c2ecf20Sopenharmony_ci if (td == R600_TD_DOWN) 4498c2ecf20Sopenharmony_ci WREG32_P(SCLK_PWRMGT_CNTL, FIR_TREND_MODE, ~FIR_TREND_MODE); 4508c2ecf20Sopenharmony_ci} 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_civoid sumo_program_vc(struct radeon_device *rdev, u32 vrc) 4538c2ecf20Sopenharmony_ci{ 4548c2ecf20Sopenharmony_ci WREG32(CG_FTV, vrc); 4558c2ecf20Sopenharmony_ci} 4568c2ecf20Sopenharmony_ci 4578c2ecf20Sopenharmony_civoid sumo_clear_vc(struct radeon_device *rdev) 4588c2ecf20Sopenharmony_ci{ 4598c2ecf20Sopenharmony_ci WREG32(CG_FTV, 0); 4608c2ecf20Sopenharmony_ci} 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_civoid sumo_program_sstp(struct radeon_device *rdev) 4638c2ecf20Sopenharmony_ci{ 4648c2ecf20Sopenharmony_ci u32 p, u; 4658c2ecf20Sopenharmony_ci u32 xclk = radeon_get_xclk(rdev); 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_ci r600_calculate_u_and_p(SUMO_SST_DFLT, 4688c2ecf20Sopenharmony_ci xclk, 16, &p, &u); 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_ci WREG32(CG_SSP, SSTU(u) | SST(p)); 4718c2ecf20Sopenharmony_ci} 4728c2ecf20Sopenharmony_ci 4738c2ecf20Sopenharmony_cistatic void sumo_set_divider_value(struct radeon_device *rdev, 4748c2ecf20Sopenharmony_ci u32 index, u32 divider) 4758c2ecf20Sopenharmony_ci{ 4768c2ecf20Sopenharmony_ci u32 reg_index = index / 4; 4778c2ecf20Sopenharmony_ci u32 field_index = index % 4; 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_ci if (field_index == 0) 4808c2ecf20Sopenharmony_ci WREG32_P(CG_SCLK_DPM_CTRL + (reg_index * 4), 4818c2ecf20Sopenharmony_ci SCLK_FSTATE_0_DIV(divider), ~SCLK_FSTATE_0_DIV_MASK); 4828c2ecf20Sopenharmony_ci else if (field_index == 1) 4838c2ecf20Sopenharmony_ci WREG32_P(CG_SCLK_DPM_CTRL + (reg_index * 4), 4848c2ecf20Sopenharmony_ci SCLK_FSTATE_1_DIV(divider), ~SCLK_FSTATE_1_DIV_MASK); 4858c2ecf20Sopenharmony_ci else if (field_index == 2) 4868c2ecf20Sopenharmony_ci WREG32_P(CG_SCLK_DPM_CTRL + (reg_index * 4), 4878c2ecf20Sopenharmony_ci SCLK_FSTATE_2_DIV(divider), ~SCLK_FSTATE_2_DIV_MASK); 4888c2ecf20Sopenharmony_ci else if (field_index == 3) 4898c2ecf20Sopenharmony_ci WREG32_P(CG_SCLK_DPM_CTRL + (reg_index * 4), 4908c2ecf20Sopenharmony_ci SCLK_FSTATE_3_DIV(divider), ~SCLK_FSTATE_3_DIV_MASK); 4918c2ecf20Sopenharmony_ci} 4928c2ecf20Sopenharmony_ci 4938c2ecf20Sopenharmony_cistatic void sumo_set_ds_dividers(struct radeon_device *rdev, 4948c2ecf20Sopenharmony_ci u32 index, u32 divider) 4958c2ecf20Sopenharmony_ci{ 4968c2ecf20Sopenharmony_ci struct sumo_power_info *pi = sumo_get_pi(rdev); 4978c2ecf20Sopenharmony_ci 4988c2ecf20Sopenharmony_ci if (pi->enable_sclk_ds) { 4998c2ecf20Sopenharmony_ci u32 dpm_ctrl = RREG32(CG_SCLK_DPM_CTRL_6); 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_ci dpm_ctrl &= ~(0x7 << (index * 3)); 5028c2ecf20Sopenharmony_ci dpm_ctrl |= (divider << (index * 3)); 5038c2ecf20Sopenharmony_ci WREG32(CG_SCLK_DPM_CTRL_6, dpm_ctrl); 5048c2ecf20Sopenharmony_ci } 5058c2ecf20Sopenharmony_ci} 5068c2ecf20Sopenharmony_ci 5078c2ecf20Sopenharmony_cistatic void sumo_set_ss_dividers(struct radeon_device *rdev, 5088c2ecf20Sopenharmony_ci u32 index, u32 divider) 5098c2ecf20Sopenharmony_ci{ 5108c2ecf20Sopenharmony_ci struct sumo_power_info *pi = sumo_get_pi(rdev); 5118c2ecf20Sopenharmony_ci 5128c2ecf20Sopenharmony_ci if (pi->enable_sclk_ds) { 5138c2ecf20Sopenharmony_ci u32 dpm_ctrl = RREG32(CG_SCLK_DPM_CTRL_11); 5148c2ecf20Sopenharmony_ci 5158c2ecf20Sopenharmony_ci dpm_ctrl &= ~(0x7 << (index * 3)); 5168c2ecf20Sopenharmony_ci dpm_ctrl |= (divider << (index * 3)); 5178c2ecf20Sopenharmony_ci WREG32(CG_SCLK_DPM_CTRL_11, dpm_ctrl); 5188c2ecf20Sopenharmony_ci } 5198c2ecf20Sopenharmony_ci} 5208c2ecf20Sopenharmony_ci 5218c2ecf20Sopenharmony_cistatic void sumo_set_vid(struct radeon_device *rdev, u32 index, u32 vid) 5228c2ecf20Sopenharmony_ci{ 5238c2ecf20Sopenharmony_ci u32 voltage_cntl = RREG32(CG_DPM_VOLTAGE_CNTL); 5248c2ecf20Sopenharmony_ci 5258c2ecf20Sopenharmony_ci voltage_cntl &= ~(DPM_STATE0_LEVEL_MASK << (index * 2)); 5268c2ecf20Sopenharmony_ci voltage_cntl |= (vid << (DPM_STATE0_LEVEL_SHIFT + index * 2)); 5278c2ecf20Sopenharmony_ci WREG32(CG_DPM_VOLTAGE_CNTL, voltage_cntl); 5288c2ecf20Sopenharmony_ci} 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_cistatic void sumo_set_allos_gnb_slow(struct radeon_device *rdev, u32 index, u32 gnb_slow) 5318c2ecf20Sopenharmony_ci{ 5328c2ecf20Sopenharmony_ci struct sumo_power_info *pi = sumo_get_pi(rdev); 5338c2ecf20Sopenharmony_ci u32 temp = gnb_slow; 5348c2ecf20Sopenharmony_ci u32 cg_sclk_dpm_ctrl_3; 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_ci if (pi->driver_nbps_policy_disable) 5378c2ecf20Sopenharmony_ci temp = 1; 5388c2ecf20Sopenharmony_ci 5398c2ecf20Sopenharmony_ci cg_sclk_dpm_ctrl_3 = RREG32(CG_SCLK_DPM_CTRL_3); 5408c2ecf20Sopenharmony_ci cg_sclk_dpm_ctrl_3 &= ~(GNB_SLOW_FSTATE_0_MASK << index); 5418c2ecf20Sopenharmony_ci cg_sclk_dpm_ctrl_3 |= (temp << (GNB_SLOW_FSTATE_0_SHIFT + index)); 5428c2ecf20Sopenharmony_ci 5438c2ecf20Sopenharmony_ci WREG32(CG_SCLK_DPM_CTRL_3, cg_sclk_dpm_ctrl_3); 5448c2ecf20Sopenharmony_ci} 5458c2ecf20Sopenharmony_ci 5468c2ecf20Sopenharmony_cistatic void sumo_program_power_level(struct radeon_device *rdev, 5478c2ecf20Sopenharmony_ci struct sumo_pl *pl, u32 index) 5488c2ecf20Sopenharmony_ci{ 5498c2ecf20Sopenharmony_ci struct sumo_power_info *pi = sumo_get_pi(rdev); 5508c2ecf20Sopenharmony_ci int ret; 5518c2ecf20Sopenharmony_ci struct atom_clock_dividers dividers; 5528c2ecf20Sopenharmony_ci u32 ds_en = RREG32(DEEP_SLEEP_CNTL) & ENABLE_DS; 5538c2ecf20Sopenharmony_ci 5548c2ecf20Sopenharmony_ci ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM, 5558c2ecf20Sopenharmony_ci pl->sclk, false, ÷rs); 5568c2ecf20Sopenharmony_ci if (ret) 5578c2ecf20Sopenharmony_ci return; 5588c2ecf20Sopenharmony_ci 5598c2ecf20Sopenharmony_ci sumo_set_divider_value(rdev, index, dividers.post_div); 5608c2ecf20Sopenharmony_ci 5618c2ecf20Sopenharmony_ci sumo_set_vid(rdev, index, pl->vddc_index); 5628c2ecf20Sopenharmony_ci 5638c2ecf20Sopenharmony_ci if (pl->ss_divider_index == 0 || pl->ds_divider_index == 0) { 5648c2ecf20Sopenharmony_ci if (ds_en) 5658c2ecf20Sopenharmony_ci WREG32_P(DEEP_SLEEP_CNTL, 0, ~ENABLE_DS); 5668c2ecf20Sopenharmony_ci } else { 5678c2ecf20Sopenharmony_ci sumo_set_ss_dividers(rdev, index, pl->ss_divider_index); 5688c2ecf20Sopenharmony_ci sumo_set_ds_dividers(rdev, index, pl->ds_divider_index); 5698c2ecf20Sopenharmony_ci 5708c2ecf20Sopenharmony_ci if (!ds_en) 5718c2ecf20Sopenharmony_ci WREG32_P(DEEP_SLEEP_CNTL, ENABLE_DS, ~ENABLE_DS); 5728c2ecf20Sopenharmony_ci } 5738c2ecf20Sopenharmony_ci 5748c2ecf20Sopenharmony_ci sumo_set_allos_gnb_slow(rdev, index, pl->allow_gnb_slow); 5758c2ecf20Sopenharmony_ci 5768c2ecf20Sopenharmony_ci if (pi->enable_boost) 5778c2ecf20Sopenharmony_ci sumo_set_tdp_limit(rdev, index, pl->sclk_dpm_tdp_limit); 5788c2ecf20Sopenharmony_ci} 5798c2ecf20Sopenharmony_ci 5808c2ecf20Sopenharmony_cistatic void sumo_power_level_enable(struct radeon_device *rdev, u32 index, bool enable) 5818c2ecf20Sopenharmony_ci{ 5828c2ecf20Sopenharmony_ci u32 reg_index = index / 4; 5838c2ecf20Sopenharmony_ci u32 field_index = index % 4; 5848c2ecf20Sopenharmony_ci 5858c2ecf20Sopenharmony_ci if (field_index == 0) 5868c2ecf20Sopenharmony_ci WREG32_P(CG_SCLK_DPM_CTRL + (reg_index * 4), 5878c2ecf20Sopenharmony_ci enable ? SCLK_FSTATE_0_VLD : 0, ~SCLK_FSTATE_0_VLD); 5888c2ecf20Sopenharmony_ci else if (field_index == 1) 5898c2ecf20Sopenharmony_ci WREG32_P(CG_SCLK_DPM_CTRL + (reg_index * 4), 5908c2ecf20Sopenharmony_ci enable ? SCLK_FSTATE_1_VLD : 0, ~SCLK_FSTATE_1_VLD); 5918c2ecf20Sopenharmony_ci else if (field_index == 2) 5928c2ecf20Sopenharmony_ci WREG32_P(CG_SCLK_DPM_CTRL + (reg_index * 4), 5938c2ecf20Sopenharmony_ci enable ? SCLK_FSTATE_2_VLD : 0, ~SCLK_FSTATE_2_VLD); 5948c2ecf20Sopenharmony_ci else if (field_index == 3) 5958c2ecf20Sopenharmony_ci WREG32_P(CG_SCLK_DPM_CTRL + (reg_index * 4), 5968c2ecf20Sopenharmony_ci enable ? SCLK_FSTATE_3_VLD : 0, ~SCLK_FSTATE_3_VLD); 5978c2ecf20Sopenharmony_ci} 5988c2ecf20Sopenharmony_ci 5998c2ecf20Sopenharmony_cistatic bool sumo_dpm_enabled(struct radeon_device *rdev) 6008c2ecf20Sopenharmony_ci{ 6018c2ecf20Sopenharmony_ci if (RREG32(CG_SCLK_DPM_CTRL_3) & DPM_SCLK_ENABLE) 6028c2ecf20Sopenharmony_ci return true; 6038c2ecf20Sopenharmony_ci else 6048c2ecf20Sopenharmony_ci return false; 6058c2ecf20Sopenharmony_ci} 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_cistatic void sumo_start_dpm(struct radeon_device *rdev) 6088c2ecf20Sopenharmony_ci{ 6098c2ecf20Sopenharmony_ci WREG32_P(CG_SCLK_DPM_CTRL_3, DPM_SCLK_ENABLE, ~DPM_SCLK_ENABLE); 6108c2ecf20Sopenharmony_ci} 6118c2ecf20Sopenharmony_ci 6128c2ecf20Sopenharmony_cistatic void sumo_stop_dpm(struct radeon_device *rdev) 6138c2ecf20Sopenharmony_ci{ 6148c2ecf20Sopenharmony_ci WREG32_P(CG_SCLK_DPM_CTRL_3, 0, ~DPM_SCLK_ENABLE); 6158c2ecf20Sopenharmony_ci} 6168c2ecf20Sopenharmony_ci 6178c2ecf20Sopenharmony_cistatic void sumo_set_forced_mode(struct radeon_device *rdev, bool enable) 6188c2ecf20Sopenharmony_ci{ 6198c2ecf20Sopenharmony_ci if (enable) 6208c2ecf20Sopenharmony_ci WREG32_P(CG_SCLK_DPM_CTRL_3, FORCE_SCLK_STATE_EN, ~FORCE_SCLK_STATE_EN); 6218c2ecf20Sopenharmony_ci else 6228c2ecf20Sopenharmony_ci WREG32_P(CG_SCLK_DPM_CTRL_3, 0, ~FORCE_SCLK_STATE_EN); 6238c2ecf20Sopenharmony_ci} 6248c2ecf20Sopenharmony_ci 6258c2ecf20Sopenharmony_cistatic void sumo_set_forced_mode_enabled(struct radeon_device *rdev) 6268c2ecf20Sopenharmony_ci{ 6278c2ecf20Sopenharmony_ci int i; 6288c2ecf20Sopenharmony_ci 6298c2ecf20Sopenharmony_ci sumo_set_forced_mode(rdev, true); 6308c2ecf20Sopenharmony_ci for (i = 0; i < rdev->usec_timeout; i++) { 6318c2ecf20Sopenharmony_ci if (RREG32(CG_SCLK_STATUS) & SCLK_OVERCLK_DETECT) 6328c2ecf20Sopenharmony_ci break; 6338c2ecf20Sopenharmony_ci udelay(1); 6348c2ecf20Sopenharmony_ci } 6358c2ecf20Sopenharmony_ci} 6368c2ecf20Sopenharmony_ci 6378c2ecf20Sopenharmony_cistatic void sumo_wait_for_level_0(struct radeon_device *rdev) 6388c2ecf20Sopenharmony_ci{ 6398c2ecf20Sopenharmony_ci int i; 6408c2ecf20Sopenharmony_ci 6418c2ecf20Sopenharmony_ci for (i = 0; i < rdev->usec_timeout; i++) { 6428c2ecf20Sopenharmony_ci if ((RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURR_SCLK_INDEX_MASK) == 0) 6438c2ecf20Sopenharmony_ci break; 6448c2ecf20Sopenharmony_ci udelay(1); 6458c2ecf20Sopenharmony_ci } 6468c2ecf20Sopenharmony_ci for (i = 0; i < rdev->usec_timeout; i++) { 6478c2ecf20Sopenharmony_ci if ((RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURR_INDEX_MASK) == 0) 6488c2ecf20Sopenharmony_ci break; 6498c2ecf20Sopenharmony_ci udelay(1); 6508c2ecf20Sopenharmony_ci } 6518c2ecf20Sopenharmony_ci} 6528c2ecf20Sopenharmony_ci 6538c2ecf20Sopenharmony_cistatic void sumo_set_forced_mode_disabled(struct radeon_device *rdev) 6548c2ecf20Sopenharmony_ci{ 6558c2ecf20Sopenharmony_ci sumo_set_forced_mode(rdev, false); 6568c2ecf20Sopenharmony_ci} 6578c2ecf20Sopenharmony_ci 6588c2ecf20Sopenharmony_cistatic void sumo_enable_power_level_0(struct radeon_device *rdev) 6598c2ecf20Sopenharmony_ci{ 6608c2ecf20Sopenharmony_ci sumo_power_level_enable(rdev, 0, true); 6618c2ecf20Sopenharmony_ci} 6628c2ecf20Sopenharmony_ci 6638c2ecf20Sopenharmony_cistatic void sumo_patch_boost_state(struct radeon_device *rdev, 6648c2ecf20Sopenharmony_ci struct radeon_ps *rps) 6658c2ecf20Sopenharmony_ci{ 6668c2ecf20Sopenharmony_ci struct sumo_power_info *pi = sumo_get_pi(rdev); 6678c2ecf20Sopenharmony_ci struct sumo_ps *new_ps = sumo_get_ps(rps); 6688c2ecf20Sopenharmony_ci 6698c2ecf20Sopenharmony_ci if (new_ps->flags & SUMO_POWERSTATE_FLAGS_BOOST_STATE) { 6708c2ecf20Sopenharmony_ci pi->boost_pl = new_ps->levels[new_ps->num_levels - 1]; 6718c2ecf20Sopenharmony_ci pi->boost_pl.sclk = pi->sys_info.boost_sclk; 6728c2ecf20Sopenharmony_ci pi->boost_pl.vddc_index = pi->sys_info.boost_vid_2bit; 6738c2ecf20Sopenharmony_ci pi->boost_pl.sclk_dpm_tdp_limit = pi->sys_info.sclk_dpm_tdp_limit_boost; 6748c2ecf20Sopenharmony_ci } 6758c2ecf20Sopenharmony_ci} 6768c2ecf20Sopenharmony_ci 6778c2ecf20Sopenharmony_cistatic void sumo_pre_notify_alt_vddnb_change(struct radeon_device *rdev, 6788c2ecf20Sopenharmony_ci struct radeon_ps *new_rps, 6798c2ecf20Sopenharmony_ci struct radeon_ps *old_rps) 6808c2ecf20Sopenharmony_ci{ 6818c2ecf20Sopenharmony_ci struct sumo_ps *new_ps = sumo_get_ps(new_rps); 6828c2ecf20Sopenharmony_ci struct sumo_ps *old_ps = sumo_get_ps(old_rps); 6838c2ecf20Sopenharmony_ci u32 nbps1_old = 0; 6848c2ecf20Sopenharmony_ci u32 nbps1_new = 0; 6858c2ecf20Sopenharmony_ci 6868c2ecf20Sopenharmony_ci if (old_ps != NULL) 6878c2ecf20Sopenharmony_ci nbps1_old = (old_ps->flags & SUMO_POWERSTATE_FLAGS_FORCE_NBPS1_STATE) ? 1 : 0; 6888c2ecf20Sopenharmony_ci 6898c2ecf20Sopenharmony_ci nbps1_new = (new_ps->flags & SUMO_POWERSTATE_FLAGS_FORCE_NBPS1_STATE) ? 1 : 0; 6908c2ecf20Sopenharmony_ci 6918c2ecf20Sopenharmony_ci if (nbps1_old == 1 && nbps1_new == 0) 6928c2ecf20Sopenharmony_ci sumo_smu_notify_alt_vddnb_change(rdev, 0, 0); 6938c2ecf20Sopenharmony_ci} 6948c2ecf20Sopenharmony_ci 6958c2ecf20Sopenharmony_cistatic void sumo_post_notify_alt_vddnb_change(struct radeon_device *rdev, 6968c2ecf20Sopenharmony_ci struct radeon_ps *new_rps, 6978c2ecf20Sopenharmony_ci struct radeon_ps *old_rps) 6988c2ecf20Sopenharmony_ci{ 6998c2ecf20Sopenharmony_ci struct sumo_ps *new_ps = sumo_get_ps(new_rps); 7008c2ecf20Sopenharmony_ci struct sumo_ps *old_ps = sumo_get_ps(old_rps); 7018c2ecf20Sopenharmony_ci u32 nbps1_old = 0; 7028c2ecf20Sopenharmony_ci u32 nbps1_new = 0; 7038c2ecf20Sopenharmony_ci 7048c2ecf20Sopenharmony_ci if (old_ps != NULL) 7058c2ecf20Sopenharmony_ci nbps1_old = (old_ps->flags & SUMO_POWERSTATE_FLAGS_FORCE_NBPS1_STATE)? 1 : 0; 7068c2ecf20Sopenharmony_ci 7078c2ecf20Sopenharmony_ci nbps1_new = (new_ps->flags & SUMO_POWERSTATE_FLAGS_FORCE_NBPS1_STATE)? 1 : 0; 7088c2ecf20Sopenharmony_ci 7098c2ecf20Sopenharmony_ci if (nbps1_old == 0 && nbps1_new == 1) 7108c2ecf20Sopenharmony_ci sumo_smu_notify_alt_vddnb_change(rdev, 1, 1); 7118c2ecf20Sopenharmony_ci} 7128c2ecf20Sopenharmony_ci 7138c2ecf20Sopenharmony_cistatic void sumo_enable_boost(struct radeon_device *rdev, 7148c2ecf20Sopenharmony_ci struct radeon_ps *rps, 7158c2ecf20Sopenharmony_ci bool enable) 7168c2ecf20Sopenharmony_ci{ 7178c2ecf20Sopenharmony_ci struct sumo_ps *new_ps = sumo_get_ps(rps); 7188c2ecf20Sopenharmony_ci 7198c2ecf20Sopenharmony_ci if (enable) { 7208c2ecf20Sopenharmony_ci if (new_ps->flags & SUMO_POWERSTATE_FLAGS_BOOST_STATE) 7218c2ecf20Sopenharmony_ci sumo_boost_state_enable(rdev, true); 7228c2ecf20Sopenharmony_ci } else 7238c2ecf20Sopenharmony_ci sumo_boost_state_enable(rdev, false); 7248c2ecf20Sopenharmony_ci} 7258c2ecf20Sopenharmony_ci 7268c2ecf20Sopenharmony_cistatic void sumo_set_forced_level(struct radeon_device *rdev, u32 index) 7278c2ecf20Sopenharmony_ci{ 7288c2ecf20Sopenharmony_ci WREG32_P(CG_SCLK_DPM_CTRL_3, FORCE_SCLK_STATE(index), ~FORCE_SCLK_STATE_MASK); 7298c2ecf20Sopenharmony_ci} 7308c2ecf20Sopenharmony_ci 7318c2ecf20Sopenharmony_cistatic void sumo_set_forced_level_0(struct radeon_device *rdev) 7328c2ecf20Sopenharmony_ci{ 7338c2ecf20Sopenharmony_ci sumo_set_forced_level(rdev, 0); 7348c2ecf20Sopenharmony_ci} 7358c2ecf20Sopenharmony_ci 7368c2ecf20Sopenharmony_cistatic void sumo_program_wl(struct radeon_device *rdev, 7378c2ecf20Sopenharmony_ci struct radeon_ps *rps) 7388c2ecf20Sopenharmony_ci{ 7398c2ecf20Sopenharmony_ci struct sumo_ps *new_ps = sumo_get_ps(rps); 7408c2ecf20Sopenharmony_ci u32 dpm_ctrl4 = RREG32(CG_SCLK_DPM_CTRL_4); 7418c2ecf20Sopenharmony_ci 7428c2ecf20Sopenharmony_ci dpm_ctrl4 &= 0xFFFFFF00; 7438c2ecf20Sopenharmony_ci dpm_ctrl4 |= (1 << (new_ps->num_levels - 1)); 7448c2ecf20Sopenharmony_ci 7458c2ecf20Sopenharmony_ci if (new_ps->flags & SUMO_POWERSTATE_FLAGS_BOOST_STATE) 7468c2ecf20Sopenharmony_ci dpm_ctrl4 |= (1 << BOOST_DPM_LEVEL); 7478c2ecf20Sopenharmony_ci 7488c2ecf20Sopenharmony_ci WREG32(CG_SCLK_DPM_CTRL_4, dpm_ctrl4); 7498c2ecf20Sopenharmony_ci} 7508c2ecf20Sopenharmony_ci 7518c2ecf20Sopenharmony_cistatic void sumo_program_power_levels_0_to_n(struct radeon_device *rdev, 7528c2ecf20Sopenharmony_ci struct radeon_ps *new_rps, 7538c2ecf20Sopenharmony_ci struct radeon_ps *old_rps) 7548c2ecf20Sopenharmony_ci{ 7558c2ecf20Sopenharmony_ci struct sumo_power_info *pi = sumo_get_pi(rdev); 7568c2ecf20Sopenharmony_ci struct sumo_ps *new_ps = sumo_get_ps(new_rps); 7578c2ecf20Sopenharmony_ci struct sumo_ps *old_ps = sumo_get_ps(old_rps); 7588c2ecf20Sopenharmony_ci u32 i; 7598c2ecf20Sopenharmony_ci u32 n_current_state_levels = (old_ps == NULL) ? 1 : old_ps->num_levels; 7608c2ecf20Sopenharmony_ci 7618c2ecf20Sopenharmony_ci for (i = 0; i < new_ps->num_levels; i++) { 7628c2ecf20Sopenharmony_ci sumo_program_power_level(rdev, &new_ps->levels[i], i); 7638c2ecf20Sopenharmony_ci sumo_power_level_enable(rdev, i, true); 7648c2ecf20Sopenharmony_ci } 7658c2ecf20Sopenharmony_ci 7668c2ecf20Sopenharmony_ci for (i = new_ps->num_levels; i < n_current_state_levels; i++) 7678c2ecf20Sopenharmony_ci sumo_power_level_enable(rdev, i, false); 7688c2ecf20Sopenharmony_ci 7698c2ecf20Sopenharmony_ci if (new_ps->flags & SUMO_POWERSTATE_FLAGS_BOOST_STATE) 7708c2ecf20Sopenharmony_ci sumo_program_power_level(rdev, &pi->boost_pl, BOOST_DPM_LEVEL); 7718c2ecf20Sopenharmony_ci} 7728c2ecf20Sopenharmony_ci 7738c2ecf20Sopenharmony_cistatic void sumo_enable_acpi_pm(struct radeon_device *rdev) 7748c2ecf20Sopenharmony_ci{ 7758c2ecf20Sopenharmony_ci WREG32_P(GENERAL_PWRMGT, STATIC_PM_EN, ~STATIC_PM_EN); 7768c2ecf20Sopenharmony_ci} 7778c2ecf20Sopenharmony_ci 7788c2ecf20Sopenharmony_cistatic void sumo_program_power_level_enter_state(struct radeon_device *rdev) 7798c2ecf20Sopenharmony_ci{ 7808c2ecf20Sopenharmony_ci WREG32_P(CG_SCLK_DPM_CTRL_5, SCLK_FSTATE_BOOTUP(0), ~SCLK_FSTATE_BOOTUP_MASK); 7818c2ecf20Sopenharmony_ci} 7828c2ecf20Sopenharmony_ci 7838c2ecf20Sopenharmony_cistatic void sumo_program_acpi_power_level(struct radeon_device *rdev) 7848c2ecf20Sopenharmony_ci{ 7858c2ecf20Sopenharmony_ci struct sumo_power_info *pi = sumo_get_pi(rdev); 7868c2ecf20Sopenharmony_ci struct atom_clock_dividers dividers; 7878c2ecf20Sopenharmony_ci int ret; 7888c2ecf20Sopenharmony_ci 7898c2ecf20Sopenharmony_ci ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM, 7908c2ecf20Sopenharmony_ci pi->acpi_pl.sclk, 7918c2ecf20Sopenharmony_ci false, ÷rs); 7928c2ecf20Sopenharmony_ci if (ret) 7938c2ecf20Sopenharmony_ci return; 7948c2ecf20Sopenharmony_ci 7958c2ecf20Sopenharmony_ci WREG32_P(CG_ACPI_CNTL, SCLK_ACPI_DIV(dividers.post_div), ~SCLK_ACPI_DIV_MASK); 7968c2ecf20Sopenharmony_ci WREG32_P(CG_ACPI_VOLTAGE_CNTL, 0, ~ACPI_VOLTAGE_EN); 7978c2ecf20Sopenharmony_ci} 7988c2ecf20Sopenharmony_ci 7998c2ecf20Sopenharmony_cistatic void sumo_program_bootup_state(struct radeon_device *rdev) 8008c2ecf20Sopenharmony_ci{ 8018c2ecf20Sopenharmony_ci struct sumo_power_info *pi = sumo_get_pi(rdev); 8028c2ecf20Sopenharmony_ci u32 dpm_ctrl4 = RREG32(CG_SCLK_DPM_CTRL_4); 8038c2ecf20Sopenharmony_ci u32 i; 8048c2ecf20Sopenharmony_ci 8058c2ecf20Sopenharmony_ci sumo_program_power_level(rdev, &pi->boot_pl, 0); 8068c2ecf20Sopenharmony_ci 8078c2ecf20Sopenharmony_ci dpm_ctrl4 &= 0xFFFFFF00; 8088c2ecf20Sopenharmony_ci WREG32(CG_SCLK_DPM_CTRL_4, dpm_ctrl4); 8098c2ecf20Sopenharmony_ci 8108c2ecf20Sopenharmony_ci for (i = 1; i < 8; i++) 8118c2ecf20Sopenharmony_ci sumo_power_level_enable(rdev, i, false); 8128c2ecf20Sopenharmony_ci} 8138c2ecf20Sopenharmony_ci 8148c2ecf20Sopenharmony_cistatic void sumo_setup_uvd_clocks(struct radeon_device *rdev, 8158c2ecf20Sopenharmony_ci struct radeon_ps *new_rps, 8168c2ecf20Sopenharmony_ci struct radeon_ps *old_rps) 8178c2ecf20Sopenharmony_ci{ 8188c2ecf20Sopenharmony_ci struct sumo_power_info *pi = sumo_get_pi(rdev); 8198c2ecf20Sopenharmony_ci 8208c2ecf20Sopenharmony_ci if (pi->enable_gfx_power_gating) { 8218c2ecf20Sopenharmony_ci sumo_gfx_powergating_enable(rdev, false); 8228c2ecf20Sopenharmony_ci } 8238c2ecf20Sopenharmony_ci 8248c2ecf20Sopenharmony_ci radeon_set_uvd_clocks(rdev, new_rps->vclk, new_rps->dclk); 8258c2ecf20Sopenharmony_ci 8268c2ecf20Sopenharmony_ci if (pi->enable_gfx_power_gating) { 8278c2ecf20Sopenharmony_ci if (!pi->disable_gfx_power_gating_in_uvd || 8288c2ecf20Sopenharmony_ci !r600_is_uvd_state(new_rps->class, new_rps->class2)) 8298c2ecf20Sopenharmony_ci sumo_gfx_powergating_enable(rdev, true); 8308c2ecf20Sopenharmony_ci } 8318c2ecf20Sopenharmony_ci} 8328c2ecf20Sopenharmony_ci 8338c2ecf20Sopenharmony_cistatic void sumo_set_uvd_clock_before_set_eng_clock(struct radeon_device *rdev, 8348c2ecf20Sopenharmony_ci struct radeon_ps *new_rps, 8358c2ecf20Sopenharmony_ci struct radeon_ps *old_rps) 8368c2ecf20Sopenharmony_ci{ 8378c2ecf20Sopenharmony_ci struct sumo_ps *new_ps = sumo_get_ps(new_rps); 8388c2ecf20Sopenharmony_ci struct sumo_ps *current_ps = sumo_get_ps(old_rps); 8398c2ecf20Sopenharmony_ci 8408c2ecf20Sopenharmony_ci if ((new_rps->vclk == old_rps->vclk) && 8418c2ecf20Sopenharmony_ci (new_rps->dclk == old_rps->dclk)) 8428c2ecf20Sopenharmony_ci return; 8438c2ecf20Sopenharmony_ci 8448c2ecf20Sopenharmony_ci if (new_ps->levels[new_ps->num_levels - 1].sclk >= 8458c2ecf20Sopenharmony_ci current_ps->levels[current_ps->num_levels - 1].sclk) 8468c2ecf20Sopenharmony_ci return; 8478c2ecf20Sopenharmony_ci 8488c2ecf20Sopenharmony_ci sumo_setup_uvd_clocks(rdev, new_rps, old_rps); 8498c2ecf20Sopenharmony_ci} 8508c2ecf20Sopenharmony_ci 8518c2ecf20Sopenharmony_cistatic void sumo_set_uvd_clock_after_set_eng_clock(struct radeon_device *rdev, 8528c2ecf20Sopenharmony_ci struct radeon_ps *new_rps, 8538c2ecf20Sopenharmony_ci struct radeon_ps *old_rps) 8548c2ecf20Sopenharmony_ci{ 8558c2ecf20Sopenharmony_ci struct sumo_ps *new_ps = sumo_get_ps(new_rps); 8568c2ecf20Sopenharmony_ci struct sumo_ps *current_ps = sumo_get_ps(old_rps); 8578c2ecf20Sopenharmony_ci 8588c2ecf20Sopenharmony_ci if ((new_rps->vclk == old_rps->vclk) && 8598c2ecf20Sopenharmony_ci (new_rps->dclk == old_rps->dclk)) 8608c2ecf20Sopenharmony_ci return; 8618c2ecf20Sopenharmony_ci 8628c2ecf20Sopenharmony_ci if (new_ps->levels[new_ps->num_levels - 1].sclk < 8638c2ecf20Sopenharmony_ci current_ps->levels[current_ps->num_levels - 1].sclk) 8648c2ecf20Sopenharmony_ci return; 8658c2ecf20Sopenharmony_ci 8668c2ecf20Sopenharmony_ci sumo_setup_uvd_clocks(rdev, new_rps, old_rps); 8678c2ecf20Sopenharmony_ci} 8688c2ecf20Sopenharmony_ci 8698c2ecf20Sopenharmony_civoid sumo_take_smu_control(struct radeon_device *rdev, bool enable) 8708c2ecf20Sopenharmony_ci{ 8718c2ecf20Sopenharmony_ci/* This bit selects who handles display phy powergating. 8728c2ecf20Sopenharmony_ci * Clear the bit to let atom handle it. 8738c2ecf20Sopenharmony_ci * Set it to let the driver handle it. 8748c2ecf20Sopenharmony_ci * For now we just let atom handle it. 8758c2ecf20Sopenharmony_ci */ 8768c2ecf20Sopenharmony_ci#if 0 8778c2ecf20Sopenharmony_ci u32 v = RREG32(DOUT_SCRATCH3); 8788c2ecf20Sopenharmony_ci 8798c2ecf20Sopenharmony_ci if (enable) 8808c2ecf20Sopenharmony_ci v |= 0x4; 8818c2ecf20Sopenharmony_ci else 8828c2ecf20Sopenharmony_ci v &= 0xFFFFFFFB; 8838c2ecf20Sopenharmony_ci 8848c2ecf20Sopenharmony_ci WREG32(DOUT_SCRATCH3, v); 8858c2ecf20Sopenharmony_ci#endif 8868c2ecf20Sopenharmony_ci} 8878c2ecf20Sopenharmony_ci 8888c2ecf20Sopenharmony_cistatic void sumo_enable_sclk_ds(struct radeon_device *rdev, bool enable) 8898c2ecf20Sopenharmony_ci{ 8908c2ecf20Sopenharmony_ci if (enable) { 8918c2ecf20Sopenharmony_ci u32 deep_sleep_cntl = RREG32(DEEP_SLEEP_CNTL); 8928c2ecf20Sopenharmony_ci u32 deep_sleep_cntl2 = RREG32(DEEP_SLEEP_CNTL2); 8938c2ecf20Sopenharmony_ci u32 t = 1; 8948c2ecf20Sopenharmony_ci 8958c2ecf20Sopenharmony_ci deep_sleep_cntl &= ~R_DIS; 8968c2ecf20Sopenharmony_ci deep_sleep_cntl &= ~HS_MASK; 8978c2ecf20Sopenharmony_ci deep_sleep_cntl |= HS(t > 4095 ? 4095 : t); 8988c2ecf20Sopenharmony_ci 8998c2ecf20Sopenharmony_ci deep_sleep_cntl2 |= LB_UFP_EN; 9008c2ecf20Sopenharmony_ci deep_sleep_cntl2 &= INOUT_C_MASK; 9018c2ecf20Sopenharmony_ci deep_sleep_cntl2 |= INOUT_C(0xf); 9028c2ecf20Sopenharmony_ci 9038c2ecf20Sopenharmony_ci WREG32(DEEP_SLEEP_CNTL2, deep_sleep_cntl2); 9048c2ecf20Sopenharmony_ci WREG32(DEEP_SLEEP_CNTL, deep_sleep_cntl); 9058c2ecf20Sopenharmony_ci } else 9068c2ecf20Sopenharmony_ci WREG32_P(DEEP_SLEEP_CNTL, 0, ~ENABLE_DS); 9078c2ecf20Sopenharmony_ci} 9088c2ecf20Sopenharmony_ci 9098c2ecf20Sopenharmony_cistatic void sumo_program_bootup_at(struct radeon_device *rdev) 9108c2ecf20Sopenharmony_ci{ 9118c2ecf20Sopenharmony_ci WREG32_P(CG_AT_0, CG_R(0xffff), ~CG_R_MASK); 9128c2ecf20Sopenharmony_ci WREG32_P(CG_AT_0, CG_L(0), ~CG_L_MASK); 9138c2ecf20Sopenharmony_ci} 9148c2ecf20Sopenharmony_ci 9158c2ecf20Sopenharmony_cistatic void sumo_reset_am(struct radeon_device *rdev) 9168c2ecf20Sopenharmony_ci{ 9178c2ecf20Sopenharmony_ci WREG32_P(SCLK_PWRMGT_CNTL, FIR_RESET, ~FIR_RESET); 9188c2ecf20Sopenharmony_ci} 9198c2ecf20Sopenharmony_ci 9208c2ecf20Sopenharmony_cistatic void sumo_start_am(struct radeon_device *rdev) 9218c2ecf20Sopenharmony_ci{ 9228c2ecf20Sopenharmony_ci WREG32_P(SCLK_PWRMGT_CNTL, 0, ~FIR_RESET); 9238c2ecf20Sopenharmony_ci} 9248c2ecf20Sopenharmony_ci 9258c2ecf20Sopenharmony_cistatic void sumo_program_ttp(struct radeon_device *rdev) 9268c2ecf20Sopenharmony_ci{ 9278c2ecf20Sopenharmony_ci u32 xclk = radeon_get_xclk(rdev); 9288c2ecf20Sopenharmony_ci u32 p, u; 9298c2ecf20Sopenharmony_ci u32 cg_sclk_dpm_ctrl_5 = RREG32(CG_SCLK_DPM_CTRL_5); 9308c2ecf20Sopenharmony_ci 9318c2ecf20Sopenharmony_ci r600_calculate_u_and_p(1000, 9328c2ecf20Sopenharmony_ci xclk, 16, &p, &u); 9338c2ecf20Sopenharmony_ci 9348c2ecf20Sopenharmony_ci cg_sclk_dpm_ctrl_5 &= ~(TT_TP_MASK | TT_TU_MASK); 9358c2ecf20Sopenharmony_ci cg_sclk_dpm_ctrl_5 |= TT_TP(p) | TT_TU(u); 9368c2ecf20Sopenharmony_ci 9378c2ecf20Sopenharmony_ci WREG32(CG_SCLK_DPM_CTRL_5, cg_sclk_dpm_ctrl_5); 9388c2ecf20Sopenharmony_ci} 9398c2ecf20Sopenharmony_ci 9408c2ecf20Sopenharmony_cistatic void sumo_program_ttt(struct radeon_device *rdev) 9418c2ecf20Sopenharmony_ci{ 9428c2ecf20Sopenharmony_ci u32 cg_sclk_dpm_ctrl_3 = RREG32(CG_SCLK_DPM_CTRL_3); 9438c2ecf20Sopenharmony_ci struct sumo_power_info *pi = sumo_get_pi(rdev); 9448c2ecf20Sopenharmony_ci 9458c2ecf20Sopenharmony_ci cg_sclk_dpm_ctrl_3 &= ~(GNB_TT_MASK | GNB_THERMTHRO_MASK); 9468c2ecf20Sopenharmony_ci cg_sclk_dpm_ctrl_3 |= GNB_TT(pi->thermal_auto_throttling + 49); 9478c2ecf20Sopenharmony_ci 9488c2ecf20Sopenharmony_ci WREG32(CG_SCLK_DPM_CTRL_3, cg_sclk_dpm_ctrl_3); 9498c2ecf20Sopenharmony_ci} 9508c2ecf20Sopenharmony_ci 9518c2ecf20Sopenharmony_ci 9528c2ecf20Sopenharmony_cistatic void sumo_enable_voltage_scaling(struct radeon_device *rdev, bool enable) 9538c2ecf20Sopenharmony_ci{ 9548c2ecf20Sopenharmony_ci if (enable) { 9558c2ecf20Sopenharmony_ci WREG32_P(CG_DPM_VOLTAGE_CNTL, DPM_VOLTAGE_EN, ~DPM_VOLTAGE_EN); 9568c2ecf20Sopenharmony_ci WREG32_P(CG_CG_VOLTAGE_CNTL, 0, ~CG_VOLTAGE_EN); 9578c2ecf20Sopenharmony_ci } else { 9588c2ecf20Sopenharmony_ci WREG32_P(CG_CG_VOLTAGE_CNTL, CG_VOLTAGE_EN, ~CG_VOLTAGE_EN); 9598c2ecf20Sopenharmony_ci WREG32_P(CG_DPM_VOLTAGE_CNTL, 0, ~DPM_VOLTAGE_EN); 9608c2ecf20Sopenharmony_ci } 9618c2ecf20Sopenharmony_ci} 9628c2ecf20Sopenharmony_ci 9638c2ecf20Sopenharmony_cistatic void sumo_override_cnb_thermal_events(struct radeon_device *rdev) 9648c2ecf20Sopenharmony_ci{ 9658c2ecf20Sopenharmony_ci WREG32_P(CG_SCLK_DPM_CTRL_3, CNB_THERMTHRO_MASK_SCLK, 9668c2ecf20Sopenharmony_ci ~CNB_THERMTHRO_MASK_SCLK); 9678c2ecf20Sopenharmony_ci} 9688c2ecf20Sopenharmony_ci 9698c2ecf20Sopenharmony_cistatic void sumo_program_dc_hto(struct radeon_device *rdev) 9708c2ecf20Sopenharmony_ci{ 9718c2ecf20Sopenharmony_ci u32 cg_sclk_dpm_ctrl_4 = RREG32(CG_SCLK_DPM_CTRL_4); 9728c2ecf20Sopenharmony_ci u32 p, u; 9738c2ecf20Sopenharmony_ci u32 xclk = radeon_get_xclk(rdev); 9748c2ecf20Sopenharmony_ci 9758c2ecf20Sopenharmony_ci r600_calculate_u_and_p(100000, 9768c2ecf20Sopenharmony_ci xclk, 14, &p, &u); 9778c2ecf20Sopenharmony_ci 9788c2ecf20Sopenharmony_ci cg_sclk_dpm_ctrl_4 &= ~(DC_HDC_MASK | DC_HU_MASK); 9798c2ecf20Sopenharmony_ci cg_sclk_dpm_ctrl_4 |= DC_HDC(p) | DC_HU(u); 9808c2ecf20Sopenharmony_ci 9818c2ecf20Sopenharmony_ci WREG32(CG_SCLK_DPM_CTRL_4, cg_sclk_dpm_ctrl_4); 9828c2ecf20Sopenharmony_ci} 9838c2ecf20Sopenharmony_ci 9848c2ecf20Sopenharmony_cistatic void sumo_force_nbp_state(struct radeon_device *rdev, 9858c2ecf20Sopenharmony_ci struct radeon_ps *rps) 9868c2ecf20Sopenharmony_ci{ 9878c2ecf20Sopenharmony_ci struct sumo_power_info *pi = sumo_get_pi(rdev); 9888c2ecf20Sopenharmony_ci struct sumo_ps *new_ps = sumo_get_ps(rps); 9898c2ecf20Sopenharmony_ci 9908c2ecf20Sopenharmony_ci if (!pi->driver_nbps_policy_disable) { 9918c2ecf20Sopenharmony_ci if (new_ps->flags & SUMO_POWERSTATE_FLAGS_FORCE_NBPS1_STATE) 9928c2ecf20Sopenharmony_ci WREG32_P(CG_SCLK_DPM_CTRL_3, FORCE_NB_PSTATE_1, ~FORCE_NB_PSTATE_1); 9938c2ecf20Sopenharmony_ci else 9948c2ecf20Sopenharmony_ci WREG32_P(CG_SCLK_DPM_CTRL_3, 0, ~FORCE_NB_PSTATE_1); 9958c2ecf20Sopenharmony_ci } 9968c2ecf20Sopenharmony_ci} 9978c2ecf20Sopenharmony_ci 9988c2ecf20Sopenharmony_ciu32 sumo_get_sleep_divider_from_id(u32 id) 9998c2ecf20Sopenharmony_ci{ 10008c2ecf20Sopenharmony_ci return 1 << id; 10018c2ecf20Sopenharmony_ci} 10028c2ecf20Sopenharmony_ci 10038c2ecf20Sopenharmony_ciu32 sumo_get_sleep_divider_id_from_clock(struct radeon_device *rdev, 10048c2ecf20Sopenharmony_ci u32 sclk, 10058c2ecf20Sopenharmony_ci u32 min_sclk_in_sr) 10068c2ecf20Sopenharmony_ci{ 10078c2ecf20Sopenharmony_ci struct sumo_power_info *pi = sumo_get_pi(rdev); 10088c2ecf20Sopenharmony_ci u32 i; 10098c2ecf20Sopenharmony_ci u32 temp; 10108c2ecf20Sopenharmony_ci u32 min = (min_sclk_in_sr > SUMO_MINIMUM_ENGINE_CLOCK) ? 10118c2ecf20Sopenharmony_ci min_sclk_in_sr : SUMO_MINIMUM_ENGINE_CLOCK; 10128c2ecf20Sopenharmony_ci 10138c2ecf20Sopenharmony_ci if (sclk < min) 10148c2ecf20Sopenharmony_ci return 0; 10158c2ecf20Sopenharmony_ci 10168c2ecf20Sopenharmony_ci if (!pi->enable_sclk_ds) 10178c2ecf20Sopenharmony_ci return 0; 10188c2ecf20Sopenharmony_ci 10198c2ecf20Sopenharmony_ci for (i = SUMO_MAX_DEEPSLEEP_DIVIDER_ID; ; i--) { 10208c2ecf20Sopenharmony_ci temp = sclk / sumo_get_sleep_divider_from_id(i); 10218c2ecf20Sopenharmony_ci 10228c2ecf20Sopenharmony_ci if (temp >= min || i == 0) 10238c2ecf20Sopenharmony_ci break; 10248c2ecf20Sopenharmony_ci } 10258c2ecf20Sopenharmony_ci return i; 10268c2ecf20Sopenharmony_ci} 10278c2ecf20Sopenharmony_ci 10288c2ecf20Sopenharmony_cistatic u32 sumo_get_valid_engine_clock(struct radeon_device *rdev, 10298c2ecf20Sopenharmony_ci u32 lower_limit) 10308c2ecf20Sopenharmony_ci{ 10318c2ecf20Sopenharmony_ci struct sumo_power_info *pi = sumo_get_pi(rdev); 10328c2ecf20Sopenharmony_ci u32 i; 10338c2ecf20Sopenharmony_ci 10348c2ecf20Sopenharmony_ci for (i = 0; i < pi->sys_info.sclk_voltage_mapping_table.num_max_dpm_entries; i++) { 10358c2ecf20Sopenharmony_ci if (pi->sys_info.sclk_voltage_mapping_table.entries[i].sclk_frequency >= lower_limit) 10368c2ecf20Sopenharmony_ci return pi->sys_info.sclk_voltage_mapping_table.entries[i].sclk_frequency; 10378c2ecf20Sopenharmony_ci } 10388c2ecf20Sopenharmony_ci 10398c2ecf20Sopenharmony_ci return pi->sys_info.sclk_voltage_mapping_table.entries[pi->sys_info.sclk_voltage_mapping_table.num_max_dpm_entries - 1].sclk_frequency; 10408c2ecf20Sopenharmony_ci} 10418c2ecf20Sopenharmony_ci 10428c2ecf20Sopenharmony_cistatic void sumo_patch_thermal_state(struct radeon_device *rdev, 10438c2ecf20Sopenharmony_ci struct sumo_ps *ps, 10448c2ecf20Sopenharmony_ci struct sumo_ps *current_ps) 10458c2ecf20Sopenharmony_ci{ 10468c2ecf20Sopenharmony_ci struct sumo_power_info *pi = sumo_get_pi(rdev); 10478c2ecf20Sopenharmony_ci u32 sclk_in_sr = pi->sys_info.min_sclk; /* ??? */ 10488c2ecf20Sopenharmony_ci u32 current_vddc; 10498c2ecf20Sopenharmony_ci u32 current_sclk; 10508c2ecf20Sopenharmony_ci u32 current_index = 0; 10518c2ecf20Sopenharmony_ci 10528c2ecf20Sopenharmony_ci if (current_ps) { 10538c2ecf20Sopenharmony_ci current_vddc = current_ps->levels[current_index].vddc_index; 10548c2ecf20Sopenharmony_ci current_sclk = current_ps->levels[current_index].sclk; 10558c2ecf20Sopenharmony_ci } else { 10568c2ecf20Sopenharmony_ci current_vddc = pi->boot_pl.vddc_index; 10578c2ecf20Sopenharmony_ci current_sclk = pi->boot_pl.sclk; 10588c2ecf20Sopenharmony_ci } 10598c2ecf20Sopenharmony_ci 10608c2ecf20Sopenharmony_ci ps->levels[0].vddc_index = current_vddc; 10618c2ecf20Sopenharmony_ci 10628c2ecf20Sopenharmony_ci if (ps->levels[0].sclk > current_sclk) 10638c2ecf20Sopenharmony_ci ps->levels[0].sclk = current_sclk; 10648c2ecf20Sopenharmony_ci 10658c2ecf20Sopenharmony_ci ps->levels[0].ss_divider_index = 10668c2ecf20Sopenharmony_ci sumo_get_sleep_divider_id_from_clock(rdev, ps->levels[0].sclk, sclk_in_sr); 10678c2ecf20Sopenharmony_ci 10688c2ecf20Sopenharmony_ci ps->levels[0].ds_divider_index = 10698c2ecf20Sopenharmony_ci sumo_get_sleep_divider_id_from_clock(rdev, ps->levels[0].sclk, SUMO_MINIMUM_ENGINE_CLOCK); 10708c2ecf20Sopenharmony_ci 10718c2ecf20Sopenharmony_ci if (ps->levels[0].ds_divider_index > ps->levels[0].ss_divider_index + 1) 10728c2ecf20Sopenharmony_ci ps->levels[0].ds_divider_index = ps->levels[0].ss_divider_index + 1; 10738c2ecf20Sopenharmony_ci 10748c2ecf20Sopenharmony_ci if (ps->levels[0].ss_divider_index == ps->levels[0].ds_divider_index) { 10758c2ecf20Sopenharmony_ci if (ps->levels[0].ss_divider_index > 1) 10768c2ecf20Sopenharmony_ci ps->levels[0].ss_divider_index = ps->levels[0].ss_divider_index - 1; 10778c2ecf20Sopenharmony_ci } 10788c2ecf20Sopenharmony_ci 10798c2ecf20Sopenharmony_ci if (ps->levels[0].ss_divider_index == 0) 10808c2ecf20Sopenharmony_ci ps->levels[0].ds_divider_index = 0; 10818c2ecf20Sopenharmony_ci 10828c2ecf20Sopenharmony_ci if (ps->levels[0].ds_divider_index == 0) 10838c2ecf20Sopenharmony_ci ps->levels[0].ss_divider_index = 0; 10848c2ecf20Sopenharmony_ci} 10858c2ecf20Sopenharmony_ci 10868c2ecf20Sopenharmony_cistatic void sumo_apply_state_adjust_rules(struct radeon_device *rdev, 10878c2ecf20Sopenharmony_ci struct radeon_ps *new_rps, 10888c2ecf20Sopenharmony_ci struct radeon_ps *old_rps) 10898c2ecf20Sopenharmony_ci{ 10908c2ecf20Sopenharmony_ci struct sumo_ps *ps = sumo_get_ps(new_rps); 10918c2ecf20Sopenharmony_ci struct sumo_ps *current_ps = sumo_get_ps(old_rps); 10928c2ecf20Sopenharmony_ci struct sumo_power_info *pi = sumo_get_pi(rdev); 10938c2ecf20Sopenharmony_ci u32 min_voltage = 0; /* ??? */ 10948c2ecf20Sopenharmony_ci u32 min_sclk = pi->sys_info.min_sclk; /* XXX check against disp reqs */ 10958c2ecf20Sopenharmony_ci u32 sclk_in_sr = pi->sys_info.min_sclk; /* ??? */ 10968c2ecf20Sopenharmony_ci u32 i; 10978c2ecf20Sopenharmony_ci 10988c2ecf20Sopenharmony_ci if (new_rps->class & ATOM_PPLIB_CLASSIFICATION_THERMAL) 10998c2ecf20Sopenharmony_ci return sumo_patch_thermal_state(rdev, ps, current_ps); 11008c2ecf20Sopenharmony_ci 11018c2ecf20Sopenharmony_ci if (pi->enable_boost) { 11028c2ecf20Sopenharmony_ci if (new_rps->class & ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE) 11038c2ecf20Sopenharmony_ci ps->flags |= SUMO_POWERSTATE_FLAGS_BOOST_STATE; 11048c2ecf20Sopenharmony_ci } 11058c2ecf20Sopenharmony_ci 11068c2ecf20Sopenharmony_ci if ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_UI_BATTERY) || 11078c2ecf20Sopenharmony_ci (new_rps->class & ATOM_PPLIB_CLASSIFICATION_SDSTATE) || 11088c2ecf20Sopenharmony_ci (new_rps->class & ATOM_PPLIB_CLASSIFICATION_HDSTATE)) 11098c2ecf20Sopenharmony_ci ps->flags |= SUMO_POWERSTATE_FLAGS_FORCE_NBPS1_STATE; 11108c2ecf20Sopenharmony_ci 11118c2ecf20Sopenharmony_ci for (i = 0; i < ps->num_levels; i++) { 11128c2ecf20Sopenharmony_ci if (ps->levels[i].vddc_index < min_voltage) 11138c2ecf20Sopenharmony_ci ps->levels[i].vddc_index = min_voltage; 11148c2ecf20Sopenharmony_ci 11158c2ecf20Sopenharmony_ci if (ps->levels[i].sclk < min_sclk) 11168c2ecf20Sopenharmony_ci ps->levels[i].sclk = 11178c2ecf20Sopenharmony_ci sumo_get_valid_engine_clock(rdev, min_sclk); 11188c2ecf20Sopenharmony_ci 11198c2ecf20Sopenharmony_ci ps->levels[i].ss_divider_index = 11208c2ecf20Sopenharmony_ci sumo_get_sleep_divider_id_from_clock(rdev, ps->levels[i].sclk, sclk_in_sr); 11218c2ecf20Sopenharmony_ci 11228c2ecf20Sopenharmony_ci ps->levels[i].ds_divider_index = 11238c2ecf20Sopenharmony_ci sumo_get_sleep_divider_id_from_clock(rdev, ps->levels[i].sclk, SUMO_MINIMUM_ENGINE_CLOCK); 11248c2ecf20Sopenharmony_ci 11258c2ecf20Sopenharmony_ci if (ps->levels[i].ds_divider_index > ps->levels[i].ss_divider_index + 1) 11268c2ecf20Sopenharmony_ci ps->levels[i].ds_divider_index = ps->levels[i].ss_divider_index + 1; 11278c2ecf20Sopenharmony_ci 11288c2ecf20Sopenharmony_ci if (ps->levels[i].ss_divider_index == ps->levels[i].ds_divider_index) { 11298c2ecf20Sopenharmony_ci if (ps->levels[i].ss_divider_index > 1) 11308c2ecf20Sopenharmony_ci ps->levels[i].ss_divider_index = ps->levels[i].ss_divider_index - 1; 11318c2ecf20Sopenharmony_ci } 11328c2ecf20Sopenharmony_ci 11338c2ecf20Sopenharmony_ci if (ps->levels[i].ss_divider_index == 0) 11348c2ecf20Sopenharmony_ci ps->levels[i].ds_divider_index = 0; 11358c2ecf20Sopenharmony_ci 11368c2ecf20Sopenharmony_ci if (ps->levels[i].ds_divider_index == 0) 11378c2ecf20Sopenharmony_ci ps->levels[i].ss_divider_index = 0; 11388c2ecf20Sopenharmony_ci 11398c2ecf20Sopenharmony_ci if (ps->flags & SUMO_POWERSTATE_FLAGS_FORCE_NBPS1_STATE) 11408c2ecf20Sopenharmony_ci ps->levels[i].allow_gnb_slow = 1; 11418c2ecf20Sopenharmony_ci else if ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE) || 11428c2ecf20Sopenharmony_ci (new_rps->class2 & ATOM_PPLIB_CLASSIFICATION2_MVC)) 11438c2ecf20Sopenharmony_ci ps->levels[i].allow_gnb_slow = 0; 11448c2ecf20Sopenharmony_ci else if (i == ps->num_levels - 1) 11458c2ecf20Sopenharmony_ci ps->levels[i].allow_gnb_slow = 0; 11468c2ecf20Sopenharmony_ci else 11478c2ecf20Sopenharmony_ci ps->levels[i].allow_gnb_slow = 1; 11488c2ecf20Sopenharmony_ci } 11498c2ecf20Sopenharmony_ci} 11508c2ecf20Sopenharmony_ci 11518c2ecf20Sopenharmony_cistatic void sumo_cleanup_asic(struct radeon_device *rdev) 11528c2ecf20Sopenharmony_ci{ 11538c2ecf20Sopenharmony_ci sumo_take_smu_control(rdev, false); 11548c2ecf20Sopenharmony_ci} 11558c2ecf20Sopenharmony_ci 11568c2ecf20Sopenharmony_cistatic int sumo_set_thermal_temperature_range(struct radeon_device *rdev, 11578c2ecf20Sopenharmony_ci int min_temp, int max_temp) 11588c2ecf20Sopenharmony_ci{ 11598c2ecf20Sopenharmony_ci int low_temp = 0 * 1000; 11608c2ecf20Sopenharmony_ci int high_temp = 255 * 1000; 11618c2ecf20Sopenharmony_ci 11628c2ecf20Sopenharmony_ci if (low_temp < min_temp) 11638c2ecf20Sopenharmony_ci low_temp = min_temp; 11648c2ecf20Sopenharmony_ci if (high_temp > max_temp) 11658c2ecf20Sopenharmony_ci high_temp = max_temp; 11668c2ecf20Sopenharmony_ci if (high_temp < low_temp) { 11678c2ecf20Sopenharmony_ci DRM_ERROR("invalid thermal range: %d - %d\n", low_temp, high_temp); 11688c2ecf20Sopenharmony_ci return -EINVAL; 11698c2ecf20Sopenharmony_ci } 11708c2ecf20Sopenharmony_ci 11718c2ecf20Sopenharmony_ci WREG32_P(CG_THERMAL_INT, DIG_THERM_INTH(49 + (high_temp / 1000)), ~DIG_THERM_INTH_MASK); 11728c2ecf20Sopenharmony_ci WREG32_P(CG_THERMAL_INT, DIG_THERM_INTL(49 + (low_temp / 1000)), ~DIG_THERM_INTL_MASK); 11738c2ecf20Sopenharmony_ci 11748c2ecf20Sopenharmony_ci rdev->pm.dpm.thermal.min_temp = low_temp; 11758c2ecf20Sopenharmony_ci rdev->pm.dpm.thermal.max_temp = high_temp; 11768c2ecf20Sopenharmony_ci 11778c2ecf20Sopenharmony_ci return 0; 11788c2ecf20Sopenharmony_ci} 11798c2ecf20Sopenharmony_ci 11808c2ecf20Sopenharmony_cistatic void sumo_update_current_ps(struct radeon_device *rdev, 11818c2ecf20Sopenharmony_ci struct radeon_ps *rps) 11828c2ecf20Sopenharmony_ci{ 11838c2ecf20Sopenharmony_ci struct sumo_ps *new_ps = sumo_get_ps(rps); 11848c2ecf20Sopenharmony_ci struct sumo_power_info *pi = sumo_get_pi(rdev); 11858c2ecf20Sopenharmony_ci 11868c2ecf20Sopenharmony_ci pi->current_rps = *rps; 11878c2ecf20Sopenharmony_ci pi->current_ps = *new_ps; 11888c2ecf20Sopenharmony_ci pi->current_rps.ps_priv = &pi->current_ps; 11898c2ecf20Sopenharmony_ci} 11908c2ecf20Sopenharmony_ci 11918c2ecf20Sopenharmony_cistatic void sumo_update_requested_ps(struct radeon_device *rdev, 11928c2ecf20Sopenharmony_ci struct radeon_ps *rps) 11938c2ecf20Sopenharmony_ci{ 11948c2ecf20Sopenharmony_ci struct sumo_ps *new_ps = sumo_get_ps(rps); 11958c2ecf20Sopenharmony_ci struct sumo_power_info *pi = sumo_get_pi(rdev); 11968c2ecf20Sopenharmony_ci 11978c2ecf20Sopenharmony_ci pi->requested_rps = *rps; 11988c2ecf20Sopenharmony_ci pi->requested_ps = *new_ps; 11998c2ecf20Sopenharmony_ci pi->requested_rps.ps_priv = &pi->requested_ps; 12008c2ecf20Sopenharmony_ci} 12018c2ecf20Sopenharmony_ci 12028c2ecf20Sopenharmony_ciint sumo_dpm_enable(struct radeon_device *rdev) 12038c2ecf20Sopenharmony_ci{ 12048c2ecf20Sopenharmony_ci struct sumo_power_info *pi = sumo_get_pi(rdev); 12058c2ecf20Sopenharmony_ci 12068c2ecf20Sopenharmony_ci if (sumo_dpm_enabled(rdev)) 12078c2ecf20Sopenharmony_ci return -EINVAL; 12088c2ecf20Sopenharmony_ci 12098c2ecf20Sopenharmony_ci sumo_program_bootup_state(rdev); 12108c2ecf20Sopenharmony_ci sumo_init_bsp(rdev); 12118c2ecf20Sopenharmony_ci sumo_reset_am(rdev); 12128c2ecf20Sopenharmony_ci sumo_program_tp(rdev); 12138c2ecf20Sopenharmony_ci sumo_program_bootup_at(rdev); 12148c2ecf20Sopenharmony_ci sumo_start_am(rdev); 12158c2ecf20Sopenharmony_ci if (pi->enable_auto_thermal_throttling) { 12168c2ecf20Sopenharmony_ci sumo_program_ttp(rdev); 12178c2ecf20Sopenharmony_ci sumo_program_ttt(rdev); 12188c2ecf20Sopenharmony_ci } 12198c2ecf20Sopenharmony_ci sumo_program_dc_hto(rdev); 12208c2ecf20Sopenharmony_ci sumo_program_power_level_enter_state(rdev); 12218c2ecf20Sopenharmony_ci sumo_enable_voltage_scaling(rdev, true); 12228c2ecf20Sopenharmony_ci sumo_program_sstp(rdev); 12238c2ecf20Sopenharmony_ci sumo_program_vc(rdev, SUMO_VRC_DFLT); 12248c2ecf20Sopenharmony_ci sumo_override_cnb_thermal_events(rdev); 12258c2ecf20Sopenharmony_ci sumo_start_dpm(rdev); 12268c2ecf20Sopenharmony_ci sumo_wait_for_level_0(rdev); 12278c2ecf20Sopenharmony_ci if (pi->enable_sclk_ds) 12288c2ecf20Sopenharmony_ci sumo_enable_sclk_ds(rdev, true); 12298c2ecf20Sopenharmony_ci if (pi->enable_boost) 12308c2ecf20Sopenharmony_ci sumo_enable_boost_timer(rdev); 12318c2ecf20Sopenharmony_ci 12328c2ecf20Sopenharmony_ci sumo_update_current_ps(rdev, rdev->pm.dpm.boot_ps); 12338c2ecf20Sopenharmony_ci 12348c2ecf20Sopenharmony_ci return 0; 12358c2ecf20Sopenharmony_ci} 12368c2ecf20Sopenharmony_ci 12378c2ecf20Sopenharmony_ciint sumo_dpm_late_enable(struct radeon_device *rdev) 12388c2ecf20Sopenharmony_ci{ 12398c2ecf20Sopenharmony_ci int ret; 12408c2ecf20Sopenharmony_ci 12418c2ecf20Sopenharmony_ci ret = sumo_enable_clock_power_gating(rdev); 12428c2ecf20Sopenharmony_ci if (ret) 12438c2ecf20Sopenharmony_ci return ret; 12448c2ecf20Sopenharmony_ci 12458c2ecf20Sopenharmony_ci if (rdev->irq.installed && 12468c2ecf20Sopenharmony_ci r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) { 12478c2ecf20Sopenharmony_ci ret = sumo_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX); 12488c2ecf20Sopenharmony_ci if (ret) 12498c2ecf20Sopenharmony_ci return ret; 12508c2ecf20Sopenharmony_ci rdev->irq.dpm_thermal = true; 12518c2ecf20Sopenharmony_ci radeon_irq_set(rdev); 12528c2ecf20Sopenharmony_ci } 12538c2ecf20Sopenharmony_ci 12548c2ecf20Sopenharmony_ci return 0; 12558c2ecf20Sopenharmony_ci} 12568c2ecf20Sopenharmony_ci 12578c2ecf20Sopenharmony_civoid sumo_dpm_disable(struct radeon_device *rdev) 12588c2ecf20Sopenharmony_ci{ 12598c2ecf20Sopenharmony_ci struct sumo_power_info *pi = sumo_get_pi(rdev); 12608c2ecf20Sopenharmony_ci 12618c2ecf20Sopenharmony_ci if (!sumo_dpm_enabled(rdev)) 12628c2ecf20Sopenharmony_ci return; 12638c2ecf20Sopenharmony_ci sumo_disable_clock_power_gating(rdev); 12648c2ecf20Sopenharmony_ci if (pi->enable_sclk_ds) 12658c2ecf20Sopenharmony_ci sumo_enable_sclk_ds(rdev, false); 12668c2ecf20Sopenharmony_ci sumo_clear_vc(rdev); 12678c2ecf20Sopenharmony_ci sumo_wait_for_level_0(rdev); 12688c2ecf20Sopenharmony_ci sumo_stop_dpm(rdev); 12698c2ecf20Sopenharmony_ci sumo_enable_voltage_scaling(rdev, false); 12708c2ecf20Sopenharmony_ci 12718c2ecf20Sopenharmony_ci if (rdev->irq.installed && 12728c2ecf20Sopenharmony_ci r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) { 12738c2ecf20Sopenharmony_ci rdev->irq.dpm_thermal = false; 12748c2ecf20Sopenharmony_ci radeon_irq_set(rdev); 12758c2ecf20Sopenharmony_ci } 12768c2ecf20Sopenharmony_ci 12778c2ecf20Sopenharmony_ci sumo_update_current_ps(rdev, rdev->pm.dpm.boot_ps); 12788c2ecf20Sopenharmony_ci} 12798c2ecf20Sopenharmony_ci 12808c2ecf20Sopenharmony_ciint sumo_dpm_pre_set_power_state(struct radeon_device *rdev) 12818c2ecf20Sopenharmony_ci{ 12828c2ecf20Sopenharmony_ci struct sumo_power_info *pi = sumo_get_pi(rdev); 12838c2ecf20Sopenharmony_ci struct radeon_ps requested_ps = *rdev->pm.dpm.requested_ps; 12848c2ecf20Sopenharmony_ci struct radeon_ps *new_ps = &requested_ps; 12858c2ecf20Sopenharmony_ci 12868c2ecf20Sopenharmony_ci sumo_update_requested_ps(rdev, new_ps); 12878c2ecf20Sopenharmony_ci 12888c2ecf20Sopenharmony_ci if (pi->enable_dynamic_patch_ps) 12898c2ecf20Sopenharmony_ci sumo_apply_state_adjust_rules(rdev, 12908c2ecf20Sopenharmony_ci &pi->requested_rps, 12918c2ecf20Sopenharmony_ci &pi->current_rps); 12928c2ecf20Sopenharmony_ci 12938c2ecf20Sopenharmony_ci return 0; 12948c2ecf20Sopenharmony_ci} 12958c2ecf20Sopenharmony_ci 12968c2ecf20Sopenharmony_ciint sumo_dpm_set_power_state(struct radeon_device *rdev) 12978c2ecf20Sopenharmony_ci{ 12988c2ecf20Sopenharmony_ci struct sumo_power_info *pi = sumo_get_pi(rdev); 12998c2ecf20Sopenharmony_ci struct radeon_ps *new_ps = &pi->requested_rps; 13008c2ecf20Sopenharmony_ci struct radeon_ps *old_ps = &pi->current_rps; 13018c2ecf20Sopenharmony_ci 13028c2ecf20Sopenharmony_ci if (pi->enable_dpm) 13038c2ecf20Sopenharmony_ci sumo_set_uvd_clock_before_set_eng_clock(rdev, new_ps, old_ps); 13048c2ecf20Sopenharmony_ci if (pi->enable_boost) { 13058c2ecf20Sopenharmony_ci sumo_enable_boost(rdev, new_ps, false); 13068c2ecf20Sopenharmony_ci sumo_patch_boost_state(rdev, new_ps); 13078c2ecf20Sopenharmony_ci } 13088c2ecf20Sopenharmony_ci if (pi->enable_dpm) { 13098c2ecf20Sopenharmony_ci sumo_pre_notify_alt_vddnb_change(rdev, new_ps, old_ps); 13108c2ecf20Sopenharmony_ci sumo_enable_power_level_0(rdev); 13118c2ecf20Sopenharmony_ci sumo_set_forced_level_0(rdev); 13128c2ecf20Sopenharmony_ci sumo_set_forced_mode_enabled(rdev); 13138c2ecf20Sopenharmony_ci sumo_wait_for_level_0(rdev); 13148c2ecf20Sopenharmony_ci sumo_program_power_levels_0_to_n(rdev, new_ps, old_ps); 13158c2ecf20Sopenharmony_ci sumo_program_wl(rdev, new_ps); 13168c2ecf20Sopenharmony_ci sumo_program_bsp(rdev, new_ps); 13178c2ecf20Sopenharmony_ci sumo_program_at(rdev, new_ps); 13188c2ecf20Sopenharmony_ci sumo_force_nbp_state(rdev, new_ps); 13198c2ecf20Sopenharmony_ci sumo_set_forced_mode_disabled(rdev); 13208c2ecf20Sopenharmony_ci sumo_set_forced_mode_enabled(rdev); 13218c2ecf20Sopenharmony_ci sumo_set_forced_mode_disabled(rdev); 13228c2ecf20Sopenharmony_ci sumo_post_notify_alt_vddnb_change(rdev, new_ps, old_ps); 13238c2ecf20Sopenharmony_ci } 13248c2ecf20Sopenharmony_ci if (pi->enable_boost) 13258c2ecf20Sopenharmony_ci sumo_enable_boost(rdev, new_ps, true); 13268c2ecf20Sopenharmony_ci if (pi->enable_dpm) 13278c2ecf20Sopenharmony_ci sumo_set_uvd_clock_after_set_eng_clock(rdev, new_ps, old_ps); 13288c2ecf20Sopenharmony_ci 13298c2ecf20Sopenharmony_ci return 0; 13308c2ecf20Sopenharmony_ci} 13318c2ecf20Sopenharmony_ci 13328c2ecf20Sopenharmony_civoid sumo_dpm_post_set_power_state(struct radeon_device *rdev) 13338c2ecf20Sopenharmony_ci{ 13348c2ecf20Sopenharmony_ci struct sumo_power_info *pi = sumo_get_pi(rdev); 13358c2ecf20Sopenharmony_ci struct radeon_ps *new_ps = &pi->requested_rps; 13368c2ecf20Sopenharmony_ci 13378c2ecf20Sopenharmony_ci sumo_update_current_ps(rdev, new_ps); 13388c2ecf20Sopenharmony_ci} 13398c2ecf20Sopenharmony_ci 13408c2ecf20Sopenharmony_ci#if 0 13418c2ecf20Sopenharmony_civoid sumo_dpm_reset_asic(struct radeon_device *rdev) 13428c2ecf20Sopenharmony_ci{ 13438c2ecf20Sopenharmony_ci sumo_program_bootup_state(rdev); 13448c2ecf20Sopenharmony_ci sumo_enable_power_level_0(rdev); 13458c2ecf20Sopenharmony_ci sumo_set_forced_level_0(rdev); 13468c2ecf20Sopenharmony_ci sumo_set_forced_mode_enabled(rdev); 13478c2ecf20Sopenharmony_ci sumo_wait_for_level_0(rdev); 13488c2ecf20Sopenharmony_ci sumo_set_forced_mode_disabled(rdev); 13498c2ecf20Sopenharmony_ci sumo_set_forced_mode_enabled(rdev); 13508c2ecf20Sopenharmony_ci sumo_set_forced_mode_disabled(rdev); 13518c2ecf20Sopenharmony_ci} 13528c2ecf20Sopenharmony_ci#endif 13538c2ecf20Sopenharmony_ci 13548c2ecf20Sopenharmony_civoid sumo_dpm_setup_asic(struct radeon_device *rdev) 13558c2ecf20Sopenharmony_ci{ 13568c2ecf20Sopenharmony_ci struct sumo_power_info *pi = sumo_get_pi(rdev); 13578c2ecf20Sopenharmony_ci 13588c2ecf20Sopenharmony_ci sumo_initialize_m3_arb(rdev); 13598c2ecf20Sopenharmony_ci pi->fw_version = sumo_get_running_fw_version(rdev); 13608c2ecf20Sopenharmony_ci DRM_INFO("Found smc ucode version: 0x%08x\n", pi->fw_version); 13618c2ecf20Sopenharmony_ci sumo_program_acpi_power_level(rdev); 13628c2ecf20Sopenharmony_ci sumo_enable_acpi_pm(rdev); 13638c2ecf20Sopenharmony_ci sumo_take_smu_control(rdev, true); 13648c2ecf20Sopenharmony_ci} 13658c2ecf20Sopenharmony_ci 13668c2ecf20Sopenharmony_civoid sumo_dpm_display_configuration_changed(struct radeon_device *rdev) 13678c2ecf20Sopenharmony_ci{ 13688c2ecf20Sopenharmony_ci 13698c2ecf20Sopenharmony_ci} 13708c2ecf20Sopenharmony_ci 13718c2ecf20Sopenharmony_ciunion power_info { 13728c2ecf20Sopenharmony_ci struct _ATOM_POWERPLAY_INFO info; 13738c2ecf20Sopenharmony_ci struct _ATOM_POWERPLAY_INFO_V2 info_2; 13748c2ecf20Sopenharmony_ci struct _ATOM_POWERPLAY_INFO_V3 info_3; 13758c2ecf20Sopenharmony_ci struct _ATOM_PPLIB_POWERPLAYTABLE pplib; 13768c2ecf20Sopenharmony_ci struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2; 13778c2ecf20Sopenharmony_ci struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3; 13788c2ecf20Sopenharmony_ci}; 13798c2ecf20Sopenharmony_ci 13808c2ecf20Sopenharmony_ciunion pplib_clock_info { 13818c2ecf20Sopenharmony_ci struct _ATOM_PPLIB_R600_CLOCK_INFO r600; 13828c2ecf20Sopenharmony_ci struct _ATOM_PPLIB_RS780_CLOCK_INFO rs780; 13838c2ecf20Sopenharmony_ci struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO evergreen; 13848c2ecf20Sopenharmony_ci struct _ATOM_PPLIB_SUMO_CLOCK_INFO sumo; 13858c2ecf20Sopenharmony_ci}; 13868c2ecf20Sopenharmony_ci 13878c2ecf20Sopenharmony_ciunion pplib_power_state { 13888c2ecf20Sopenharmony_ci struct _ATOM_PPLIB_STATE v1; 13898c2ecf20Sopenharmony_ci struct _ATOM_PPLIB_STATE_V2 v2; 13908c2ecf20Sopenharmony_ci}; 13918c2ecf20Sopenharmony_ci 13928c2ecf20Sopenharmony_cistatic void sumo_patch_boot_state(struct radeon_device *rdev, 13938c2ecf20Sopenharmony_ci struct sumo_ps *ps) 13948c2ecf20Sopenharmony_ci{ 13958c2ecf20Sopenharmony_ci struct sumo_power_info *pi = sumo_get_pi(rdev); 13968c2ecf20Sopenharmony_ci 13978c2ecf20Sopenharmony_ci ps->num_levels = 1; 13988c2ecf20Sopenharmony_ci ps->flags = 0; 13998c2ecf20Sopenharmony_ci ps->levels[0] = pi->boot_pl; 14008c2ecf20Sopenharmony_ci} 14018c2ecf20Sopenharmony_ci 14028c2ecf20Sopenharmony_cistatic void sumo_parse_pplib_non_clock_info(struct radeon_device *rdev, 14038c2ecf20Sopenharmony_ci struct radeon_ps *rps, 14048c2ecf20Sopenharmony_ci struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info, 14058c2ecf20Sopenharmony_ci u8 table_rev) 14068c2ecf20Sopenharmony_ci{ 14078c2ecf20Sopenharmony_ci struct sumo_ps *ps = sumo_get_ps(rps); 14088c2ecf20Sopenharmony_ci 14098c2ecf20Sopenharmony_ci rps->caps = le32_to_cpu(non_clock_info->ulCapsAndSettings); 14108c2ecf20Sopenharmony_ci rps->class = le16_to_cpu(non_clock_info->usClassification); 14118c2ecf20Sopenharmony_ci rps->class2 = le16_to_cpu(non_clock_info->usClassification2); 14128c2ecf20Sopenharmony_ci 14138c2ecf20Sopenharmony_ci if (ATOM_PPLIB_NONCLOCKINFO_VER1 < table_rev) { 14148c2ecf20Sopenharmony_ci rps->vclk = le32_to_cpu(non_clock_info->ulVCLK); 14158c2ecf20Sopenharmony_ci rps->dclk = le32_to_cpu(non_clock_info->ulDCLK); 14168c2ecf20Sopenharmony_ci } else { 14178c2ecf20Sopenharmony_ci rps->vclk = 0; 14188c2ecf20Sopenharmony_ci rps->dclk = 0; 14198c2ecf20Sopenharmony_ci } 14208c2ecf20Sopenharmony_ci 14218c2ecf20Sopenharmony_ci if (rps->class & ATOM_PPLIB_CLASSIFICATION_BOOT) { 14228c2ecf20Sopenharmony_ci rdev->pm.dpm.boot_ps = rps; 14238c2ecf20Sopenharmony_ci sumo_patch_boot_state(rdev, ps); 14248c2ecf20Sopenharmony_ci } 14258c2ecf20Sopenharmony_ci if (rps->class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE) 14268c2ecf20Sopenharmony_ci rdev->pm.dpm.uvd_ps = rps; 14278c2ecf20Sopenharmony_ci} 14288c2ecf20Sopenharmony_ci 14298c2ecf20Sopenharmony_cistatic void sumo_parse_pplib_clock_info(struct radeon_device *rdev, 14308c2ecf20Sopenharmony_ci struct radeon_ps *rps, int index, 14318c2ecf20Sopenharmony_ci union pplib_clock_info *clock_info) 14328c2ecf20Sopenharmony_ci{ 14338c2ecf20Sopenharmony_ci struct sumo_power_info *pi = sumo_get_pi(rdev); 14348c2ecf20Sopenharmony_ci struct sumo_ps *ps = sumo_get_ps(rps); 14358c2ecf20Sopenharmony_ci struct sumo_pl *pl = &ps->levels[index]; 14368c2ecf20Sopenharmony_ci u32 sclk; 14378c2ecf20Sopenharmony_ci 14388c2ecf20Sopenharmony_ci sclk = le16_to_cpu(clock_info->sumo.usEngineClockLow); 14398c2ecf20Sopenharmony_ci sclk |= clock_info->sumo.ucEngineClockHigh << 16; 14408c2ecf20Sopenharmony_ci pl->sclk = sclk; 14418c2ecf20Sopenharmony_ci pl->vddc_index = clock_info->sumo.vddcIndex; 14428c2ecf20Sopenharmony_ci pl->sclk_dpm_tdp_limit = clock_info->sumo.tdpLimit; 14438c2ecf20Sopenharmony_ci 14448c2ecf20Sopenharmony_ci ps->num_levels = index + 1; 14458c2ecf20Sopenharmony_ci 14468c2ecf20Sopenharmony_ci if (pi->enable_sclk_ds) { 14478c2ecf20Sopenharmony_ci pl->ds_divider_index = 5; 14488c2ecf20Sopenharmony_ci pl->ss_divider_index = 4; 14498c2ecf20Sopenharmony_ci } 14508c2ecf20Sopenharmony_ci} 14518c2ecf20Sopenharmony_ci 14528c2ecf20Sopenharmony_cistatic int sumo_parse_power_table(struct radeon_device *rdev) 14538c2ecf20Sopenharmony_ci{ 14548c2ecf20Sopenharmony_ci struct radeon_mode_info *mode_info = &rdev->mode_info; 14558c2ecf20Sopenharmony_ci struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info; 14568c2ecf20Sopenharmony_ci union pplib_power_state *power_state; 14578c2ecf20Sopenharmony_ci int i, j, k, non_clock_array_index, clock_array_index; 14588c2ecf20Sopenharmony_ci union pplib_clock_info *clock_info; 14598c2ecf20Sopenharmony_ci struct _StateArray *state_array; 14608c2ecf20Sopenharmony_ci struct _ClockInfoArray *clock_info_array; 14618c2ecf20Sopenharmony_ci struct _NonClockInfoArray *non_clock_info_array; 14628c2ecf20Sopenharmony_ci union power_info *power_info; 14638c2ecf20Sopenharmony_ci int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); 14648c2ecf20Sopenharmony_ci u16 data_offset; 14658c2ecf20Sopenharmony_ci u8 frev, crev; 14668c2ecf20Sopenharmony_ci u8 *power_state_offset; 14678c2ecf20Sopenharmony_ci struct sumo_ps *ps; 14688c2ecf20Sopenharmony_ci 14698c2ecf20Sopenharmony_ci if (!atom_parse_data_header(mode_info->atom_context, index, NULL, 14708c2ecf20Sopenharmony_ci &frev, &crev, &data_offset)) 14718c2ecf20Sopenharmony_ci return -EINVAL; 14728c2ecf20Sopenharmony_ci power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); 14738c2ecf20Sopenharmony_ci 14748c2ecf20Sopenharmony_ci state_array = (struct _StateArray *) 14758c2ecf20Sopenharmony_ci (mode_info->atom_context->bios + data_offset + 14768c2ecf20Sopenharmony_ci le16_to_cpu(power_info->pplib.usStateArrayOffset)); 14778c2ecf20Sopenharmony_ci clock_info_array = (struct _ClockInfoArray *) 14788c2ecf20Sopenharmony_ci (mode_info->atom_context->bios + data_offset + 14798c2ecf20Sopenharmony_ci le16_to_cpu(power_info->pplib.usClockInfoArrayOffset)); 14808c2ecf20Sopenharmony_ci non_clock_info_array = (struct _NonClockInfoArray *) 14818c2ecf20Sopenharmony_ci (mode_info->atom_context->bios + data_offset + 14828c2ecf20Sopenharmony_ci le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset)); 14838c2ecf20Sopenharmony_ci 14848c2ecf20Sopenharmony_ci rdev->pm.dpm.ps = kcalloc(state_array->ucNumEntries, 14858c2ecf20Sopenharmony_ci sizeof(struct radeon_ps), 14868c2ecf20Sopenharmony_ci GFP_KERNEL); 14878c2ecf20Sopenharmony_ci if (!rdev->pm.dpm.ps) 14888c2ecf20Sopenharmony_ci return -ENOMEM; 14898c2ecf20Sopenharmony_ci power_state_offset = (u8 *)state_array->states; 14908c2ecf20Sopenharmony_ci for (i = 0; i < state_array->ucNumEntries; i++) { 14918c2ecf20Sopenharmony_ci u8 *idx; 14928c2ecf20Sopenharmony_ci power_state = (union pplib_power_state *)power_state_offset; 14938c2ecf20Sopenharmony_ci non_clock_array_index = power_state->v2.nonClockInfoIndex; 14948c2ecf20Sopenharmony_ci non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *) 14958c2ecf20Sopenharmony_ci &non_clock_info_array->nonClockInfo[non_clock_array_index]; 14968c2ecf20Sopenharmony_ci if (!rdev->pm.power_state[i].clock_info) { 14978c2ecf20Sopenharmony_ci kfree(rdev->pm.dpm.ps); 14988c2ecf20Sopenharmony_ci return -EINVAL; 14998c2ecf20Sopenharmony_ci } 15008c2ecf20Sopenharmony_ci ps = kzalloc(sizeof(struct sumo_ps), GFP_KERNEL); 15018c2ecf20Sopenharmony_ci if (ps == NULL) { 15028c2ecf20Sopenharmony_ci kfree(rdev->pm.dpm.ps); 15038c2ecf20Sopenharmony_ci return -ENOMEM; 15048c2ecf20Sopenharmony_ci } 15058c2ecf20Sopenharmony_ci rdev->pm.dpm.ps[i].ps_priv = ps; 15068c2ecf20Sopenharmony_ci k = 0; 15078c2ecf20Sopenharmony_ci idx = (u8 *)&power_state->v2.clockInfoIndex[0]; 15088c2ecf20Sopenharmony_ci for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) { 15098c2ecf20Sopenharmony_ci clock_array_index = idx[j]; 15108c2ecf20Sopenharmony_ci if (k >= SUMO_MAX_HARDWARE_POWERLEVELS) 15118c2ecf20Sopenharmony_ci break; 15128c2ecf20Sopenharmony_ci 15138c2ecf20Sopenharmony_ci clock_info = (union pplib_clock_info *) 15148c2ecf20Sopenharmony_ci ((u8 *)&clock_info_array->clockInfo[0] + 15158c2ecf20Sopenharmony_ci (clock_array_index * clock_info_array->ucEntrySize)); 15168c2ecf20Sopenharmony_ci sumo_parse_pplib_clock_info(rdev, 15178c2ecf20Sopenharmony_ci &rdev->pm.dpm.ps[i], k, 15188c2ecf20Sopenharmony_ci clock_info); 15198c2ecf20Sopenharmony_ci k++; 15208c2ecf20Sopenharmony_ci } 15218c2ecf20Sopenharmony_ci sumo_parse_pplib_non_clock_info(rdev, &rdev->pm.dpm.ps[i], 15228c2ecf20Sopenharmony_ci non_clock_info, 15238c2ecf20Sopenharmony_ci non_clock_info_array->ucEntrySize); 15248c2ecf20Sopenharmony_ci power_state_offset += 2 + power_state->v2.ucNumDPMLevels; 15258c2ecf20Sopenharmony_ci } 15268c2ecf20Sopenharmony_ci rdev->pm.dpm.num_ps = state_array->ucNumEntries; 15278c2ecf20Sopenharmony_ci return 0; 15288c2ecf20Sopenharmony_ci} 15298c2ecf20Sopenharmony_ci 15308c2ecf20Sopenharmony_ciu32 sumo_convert_vid2_to_vid7(struct radeon_device *rdev, 15318c2ecf20Sopenharmony_ci struct sumo_vid_mapping_table *vid_mapping_table, 15328c2ecf20Sopenharmony_ci u32 vid_2bit) 15338c2ecf20Sopenharmony_ci{ 15348c2ecf20Sopenharmony_ci u32 i; 15358c2ecf20Sopenharmony_ci 15368c2ecf20Sopenharmony_ci for (i = 0; i < vid_mapping_table->num_entries; i++) { 15378c2ecf20Sopenharmony_ci if (vid_mapping_table->entries[i].vid_2bit == vid_2bit) 15388c2ecf20Sopenharmony_ci return vid_mapping_table->entries[i].vid_7bit; 15398c2ecf20Sopenharmony_ci } 15408c2ecf20Sopenharmony_ci 15418c2ecf20Sopenharmony_ci return vid_mapping_table->entries[vid_mapping_table->num_entries - 1].vid_7bit; 15428c2ecf20Sopenharmony_ci} 15438c2ecf20Sopenharmony_ci 15448c2ecf20Sopenharmony_ci#if 0 15458c2ecf20Sopenharmony_ciu32 sumo_convert_vid7_to_vid2(struct radeon_device *rdev, 15468c2ecf20Sopenharmony_ci struct sumo_vid_mapping_table *vid_mapping_table, 15478c2ecf20Sopenharmony_ci u32 vid_7bit) 15488c2ecf20Sopenharmony_ci{ 15498c2ecf20Sopenharmony_ci u32 i; 15508c2ecf20Sopenharmony_ci 15518c2ecf20Sopenharmony_ci for (i = 0; i < vid_mapping_table->num_entries; i++) { 15528c2ecf20Sopenharmony_ci if (vid_mapping_table->entries[i].vid_7bit == vid_7bit) 15538c2ecf20Sopenharmony_ci return vid_mapping_table->entries[i].vid_2bit; 15548c2ecf20Sopenharmony_ci } 15558c2ecf20Sopenharmony_ci 15568c2ecf20Sopenharmony_ci return vid_mapping_table->entries[vid_mapping_table->num_entries - 1].vid_2bit; 15578c2ecf20Sopenharmony_ci} 15588c2ecf20Sopenharmony_ci#endif 15598c2ecf20Sopenharmony_ci 15608c2ecf20Sopenharmony_cistatic u16 sumo_convert_voltage_index_to_value(struct radeon_device *rdev, 15618c2ecf20Sopenharmony_ci u32 vid_2bit) 15628c2ecf20Sopenharmony_ci{ 15638c2ecf20Sopenharmony_ci struct sumo_power_info *pi = sumo_get_pi(rdev); 15648c2ecf20Sopenharmony_ci u32 vid_7bit = sumo_convert_vid2_to_vid7(rdev, &pi->sys_info.vid_mapping_table, vid_2bit); 15658c2ecf20Sopenharmony_ci 15668c2ecf20Sopenharmony_ci if (vid_7bit > 0x7C) 15678c2ecf20Sopenharmony_ci return 0; 15688c2ecf20Sopenharmony_ci 15698c2ecf20Sopenharmony_ci return (15500 - vid_7bit * 125 + 5) / 10; 15708c2ecf20Sopenharmony_ci} 15718c2ecf20Sopenharmony_ci 15728c2ecf20Sopenharmony_cistatic void sumo_construct_display_voltage_mapping_table(struct radeon_device *rdev, 15738c2ecf20Sopenharmony_ci struct sumo_disp_clock_voltage_mapping_table *disp_clk_voltage_mapping_table, 15748c2ecf20Sopenharmony_ci ATOM_CLK_VOLT_CAPABILITY *table) 15758c2ecf20Sopenharmony_ci{ 15768c2ecf20Sopenharmony_ci u32 i; 15778c2ecf20Sopenharmony_ci 15788c2ecf20Sopenharmony_ci for (i = 0; i < SUMO_MAX_NUMBER_VOLTAGES; i++) { 15798c2ecf20Sopenharmony_ci if (table[i].ulMaximumSupportedCLK == 0) 15808c2ecf20Sopenharmony_ci break; 15818c2ecf20Sopenharmony_ci 15828c2ecf20Sopenharmony_ci disp_clk_voltage_mapping_table->display_clock_frequency[i] = 15838c2ecf20Sopenharmony_ci table[i].ulMaximumSupportedCLK; 15848c2ecf20Sopenharmony_ci } 15858c2ecf20Sopenharmony_ci 15868c2ecf20Sopenharmony_ci disp_clk_voltage_mapping_table->num_max_voltage_levels = i; 15878c2ecf20Sopenharmony_ci 15888c2ecf20Sopenharmony_ci if (disp_clk_voltage_mapping_table->num_max_voltage_levels == 0) { 15898c2ecf20Sopenharmony_ci disp_clk_voltage_mapping_table->display_clock_frequency[0] = 80000; 15908c2ecf20Sopenharmony_ci disp_clk_voltage_mapping_table->num_max_voltage_levels = 1; 15918c2ecf20Sopenharmony_ci } 15928c2ecf20Sopenharmony_ci} 15938c2ecf20Sopenharmony_ci 15948c2ecf20Sopenharmony_civoid sumo_construct_sclk_voltage_mapping_table(struct radeon_device *rdev, 15958c2ecf20Sopenharmony_ci struct sumo_sclk_voltage_mapping_table *sclk_voltage_mapping_table, 15968c2ecf20Sopenharmony_ci ATOM_AVAILABLE_SCLK_LIST *table) 15978c2ecf20Sopenharmony_ci{ 15988c2ecf20Sopenharmony_ci u32 i; 15998c2ecf20Sopenharmony_ci u32 n = 0; 16008c2ecf20Sopenharmony_ci u32 prev_sclk = 0; 16018c2ecf20Sopenharmony_ci 16028c2ecf20Sopenharmony_ci for (i = 0; i < SUMO_MAX_HARDWARE_POWERLEVELS; i++) { 16038c2ecf20Sopenharmony_ci if (table[i].ulSupportedSCLK > prev_sclk) { 16048c2ecf20Sopenharmony_ci sclk_voltage_mapping_table->entries[n].sclk_frequency = 16058c2ecf20Sopenharmony_ci table[i].ulSupportedSCLK; 16068c2ecf20Sopenharmony_ci sclk_voltage_mapping_table->entries[n].vid_2bit = 16078c2ecf20Sopenharmony_ci table[i].usVoltageIndex; 16088c2ecf20Sopenharmony_ci prev_sclk = table[i].ulSupportedSCLK; 16098c2ecf20Sopenharmony_ci n++; 16108c2ecf20Sopenharmony_ci } 16118c2ecf20Sopenharmony_ci } 16128c2ecf20Sopenharmony_ci 16138c2ecf20Sopenharmony_ci sclk_voltage_mapping_table->num_max_dpm_entries = n; 16148c2ecf20Sopenharmony_ci} 16158c2ecf20Sopenharmony_ci 16168c2ecf20Sopenharmony_civoid sumo_construct_vid_mapping_table(struct radeon_device *rdev, 16178c2ecf20Sopenharmony_ci struct sumo_vid_mapping_table *vid_mapping_table, 16188c2ecf20Sopenharmony_ci ATOM_AVAILABLE_SCLK_LIST *table) 16198c2ecf20Sopenharmony_ci{ 16208c2ecf20Sopenharmony_ci u32 i, j; 16218c2ecf20Sopenharmony_ci 16228c2ecf20Sopenharmony_ci for (i = 0; i < SUMO_MAX_HARDWARE_POWERLEVELS; i++) { 16238c2ecf20Sopenharmony_ci if (table[i].ulSupportedSCLK != 0) { 16248c2ecf20Sopenharmony_ci vid_mapping_table->entries[table[i].usVoltageIndex].vid_7bit = 16258c2ecf20Sopenharmony_ci table[i].usVoltageID; 16268c2ecf20Sopenharmony_ci vid_mapping_table->entries[table[i].usVoltageIndex].vid_2bit = 16278c2ecf20Sopenharmony_ci table[i].usVoltageIndex; 16288c2ecf20Sopenharmony_ci } 16298c2ecf20Sopenharmony_ci } 16308c2ecf20Sopenharmony_ci 16318c2ecf20Sopenharmony_ci for (i = 0; i < SUMO_MAX_NUMBER_VOLTAGES; i++) { 16328c2ecf20Sopenharmony_ci if (vid_mapping_table->entries[i].vid_7bit == 0) { 16338c2ecf20Sopenharmony_ci for (j = i + 1; j < SUMO_MAX_NUMBER_VOLTAGES; j++) { 16348c2ecf20Sopenharmony_ci if (vid_mapping_table->entries[j].vid_7bit != 0) { 16358c2ecf20Sopenharmony_ci vid_mapping_table->entries[i] = 16368c2ecf20Sopenharmony_ci vid_mapping_table->entries[j]; 16378c2ecf20Sopenharmony_ci vid_mapping_table->entries[j].vid_7bit = 0; 16388c2ecf20Sopenharmony_ci break; 16398c2ecf20Sopenharmony_ci } 16408c2ecf20Sopenharmony_ci } 16418c2ecf20Sopenharmony_ci 16428c2ecf20Sopenharmony_ci if (j == SUMO_MAX_NUMBER_VOLTAGES) 16438c2ecf20Sopenharmony_ci break; 16448c2ecf20Sopenharmony_ci } 16458c2ecf20Sopenharmony_ci } 16468c2ecf20Sopenharmony_ci 16478c2ecf20Sopenharmony_ci vid_mapping_table->num_entries = i; 16488c2ecf20Sopenharmony_ci} 16498c2ecf20Sopenharmony_ci 16508c2ecf20Sopenharmony_ciunion igp_info { 16518c2ecf20Sopenharmony_ci struct _ATOM_INTEGRATED_SYSTEM_INFO info; 16528c2ecf20Sopenharmony_ci struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 info_2; 16538c2ecf20Sopenharmony_ci struct _ATOM_INTEGRATED_SYSTEM_INFO_V5 info_5; 16548c2ecf20Sopenharmony_ci struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 info_6; 16558c2ecf20Sopenharmony_ci}; 16568c2ecf20Sopenharmony_ci 16578c2ecf20Sopenharmony_cistatic int sumo_parse_sys_info_table(struct radeon_device *rdev) 16588c2ecf20Sopenharmony_ci{ 16598c2ecf20Sopenharmony_ci struct sumo_power_info *pi = sumo_get_pi(rdev); 16608c2ecf20Sopenharmony_ci struct radeon_mode_info *mode_info = &rdev->mode_info; 16618c2ecf20Sopenharmony_ci int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo); 16628c2ecf20Sopenharmony_ci union igp_info *igp_info; 16638c2ecf20Sopenharmony_ci u8 frev, crev; 16648c2ecf20Sopenharmony_ci u16 data_offset; 16658c2ecf20Sopenharmony_ci int i; 16668c2ecf20Sopenharmony_ci 16678c2ecf20Sopenharmony_ci if (atom_parse_data_header(mode_info->atom_context, index, NULL, 16688c2ecf20Sopenharmony_ci &frev, &crev, &data_offset)) { 16698c2ecf20Sopenharmony_ci igp_info = (union igp_info *)(mode_info->atom_context->bios + 16708c2ecf20Sopenharmony_ci data_offset); 16718c2ecf20Sopenharmony_ci 16728c2ecf20Sopenharmony_ci if (crev != 6) { 16738c2ecf20Sopenharmony_ci DRM_ERROR("Unsupported IGP table: %d %d\n", frev, crev); 16748c2ecf20Sopenharmony_ci return -EINVAL; 16758c2ecf20Sopenharmony_ci } 16768c2ecf20Sopenharmony_ci pi->sys_info.bootup_sclk = le32_to_cpu(igp_info->info_6.ulBootUpEngineClock); 16778c2ecf20Sopenharmony_ci pi->sys_info.min_sclk = le32_to_cpu(igp_info->info_6.ulMinEngineClock); 16788c2ecf20Sopenharmony_ci pi->sys_info.bootup_uma_clk = le32_to_cpu(igp_info->info_6.ulBootUpUMAClock); 16798c2ecf20Sopenharmony_ci pi->sys_info.bootup_nb_voltage_index = 16808c2ecf20Sopenharmony_ci le16_to_cpu(igp_info->info_6.usBootUpNBVoltage); 16818c2ecf20Sopenharmony_ci if (igp_info->info_6.ucHtcTmpLmt == 0) 16828c2ecf20Sopenharmony_ci pi->sys_info.htc_tmp_lmt = 203; 16838c2ecf20Sopenharmony_ci else 16848c2ecf20Sopenharmony_ci pi->sys_info.htc_tmp_lmt = igp_info->info_6.ucHtcTmpLmt; 16858c2ecf20Sopenharmony_ci if (igp_info->info_6.ucHtcHystLmt == 0) 16868c2ecf20Sopenharmony_ci pi->sys_info.htc_hyst_lmt = 5; 16878c2ecf20Sopenharmony_ci else 16888c2ecf20Sopenharmony_ci pi->sys_info.htc_hyst_lmt = igp_info->info_6.ucHtcHystLmt; 16898c2ecf20Sopenharmony_ci if (pi->sys_info.htc_tmp_lmt <= pi->sys_info.htc_hyst_lmt) { 16908c2ecf20Sopenharmony_ci DRM_ERROR("The htcTmpLmt should be larger than htcHystLmt.\n"); 16918c2ecf20Sopenharmony_ci } 16928c2ecf20Sopenharmony_ci for (i = 0; i < NUMBER_OF_M3ARB_PARAM_SETS; i++) { 16938c2ecf20Sopenharmony_ci pi->sys_info.csr_m3_arb_cntl_default[i] = 16948c2ecf20Sopenharmony_ci le32_to_cpu(igp_info->info_6.ulCSR_M3_ARB_CNTL_DEFAULT[i]); 16958c2ecf20Sopenharmony_ci pi->sys_info.csr_m3_arb_cntl_uvd[i] = 16968c2ecf20Sopenharmony_ci le32_to_cpu(igp_info->info_6.ulCSR_M3_ARB_CNTL_UVD[i]); 16978c2ecf20Sopenharmony_ci pi->sys_info.csr_m3_arb_cntl_fs3d[i] = 16988c2ecf20Sopenharmony_ci le32_to_cpu(igp_info->info_6.ulCSR_M3_ARB_CNTL_FS3D[i]); 16998c2ecf20Sopenharmony_ci } 17008c2ecf20Sopenharmony_ci pi->sys_info.sclk_dpm_boost_margin = 17018c2ecf20Sopenharmony_ci le32_to_cpu(igp_info->info_6.SclkDpmBoostMargin); 17028c2ecf20Sopenharmony_ci pi->sys_info.sclk_dpm_throttle_margin = 17038c2ecf20Sopenharmony_ci le32_to_cpu(igp_info->info_6.SclkDpmThrottleMargin); 17048c2ecf20Sopenharmony_ci pi->sys_info.sclk_dpm_tdp_limit_pg = 17058c2ecf20Sopenharmony_ci le16_to_cpu(igp_info->info_6.SclkDpmTdpLimitPG); 17068c2ecf20Sopenharmony_ci pi->sys_info.gnb_tdp_limit = le16_to_cpu(igp_info->info_6.GnbTdpLimit); 17078c2ecf20Sopenharmony_ci pi->sys_info.sclk_dpm_tdp_limit_boost = 17088c2ecf20Sopenharmony_ci le16_to_cpu(igp_info->info_6.SclkDpmTdpLimitBoost); 17098c2ecf20Sopenharmony_ci pi->sys_info.boost_sclk = le32_to_cpu(igp_info->info_6.ulBoostEngineCLock); 17108c2ecf20Sopenharmony_ci pi->sys_info.boost_vid_2bit = igp_info->info_6.ulBoostVid_2bit; 17118c2ecf20Sopenharmony_ci if (igp_info->info_6.EnableBoost) 17128c2ecf20Sopenharmony_ci pi->sys_info.enable_boost = true; 17138c2ecf20Sopenharmony_ci else 17148c2ecf20Sopenharmony_ci pi->sys_info.enable_boost = false; 17158c2ecf20Sopenharmony_ci sumo_construct_display_voltage_mapping_table(rdev, 17168c2ecf20Sopenharmony_ci &pi->sys_info.disp_clk_voltage_mapping_table, 17178c2ecf20Sopenharmony_ci igp_info->info_6.sDISPCLK_Voltage); 17188c2ecf20Sopenharmony_ci sumo_construct_sclk_voltage_mapping_table(rdev, 17198c2ecf20Sopenharmony_ci &pi->sys_info.sclk_voltage_mapping_table, 17208c2ecf20Sopenharmony_ci igp_info->info_6.sAvail_SCLK); 17218c2ecf20Sopenharmony_ci sumo_construct_vid_mapping_table(rdev, &pi->sys_info.vid_mapping_table, 17228c2ecf20Sopenharmony_ci igp_info->info_6.sAvail_SCLK); 17238c2ecf20Sopenharmony_ci 17248c2ecf20Sopenharmony_ci } 17258c2ecf20Sopenharmony_ci return 0; 17268c2ecf20Sopenharmony_ci} 17278c2ecf20Sopenharmony_ci 17288c2ecf20Sopenharmony_cistatic void sumo_construct_boot_and_acpi_state(struct radeon_device *rdev) 17298c2ecf20Sopenharmony_ci{ 17308c2ecf20Sopenharmony_ci struct sumo_power_info *pi = sumo_get_pi(rdev); 17318c2ecf20Sopenharmony_ci 17328c2ecf20Sopenharmony_ci pi->boot_pl.sclk = pi->sys_info.bootup_sclk; 17338c2ecf20Sopenharmony_ci pi->boot_pl.vddc_index = pi->sys_info.bootup_nb_voltage_index; 17348c2ecf20Sopenharmony_ci pi->boot_pl.ds_divider_index = 0; 17358c2ecf20Sopenharmony_ci pi->boot_pl.ss_divider_index = 0; 17368c2ecf20Sopenharmony_ci pi->boot_pl.allow_gnb_slow = 1; 17378c2ecf20Sopenharmony_ci pi->acpi_pl = pi->boot_pl; 17388c2ecf20Sopenharmony_ci pi->current_ps.num_levels = 1; 17398c2ecf20Sopenharmony_ci pi->current_ps.levels[0] = pi->boot_pl; 17408c2ecf20Sopenharmony_ci} 17418c2ecf20Sopenharmony_ci 17428c2ecf20Sopenharmony_ciint sumo_dpm_init(struct radeon_device *rdev) 17438c2ecf20Sopenharmony_ci{ 17448c2ecf20Sopenharmony_ci struct sumo_power_info *pi; 17458c2ecf20Sopenharmony_ci u32 hw_rev = (RREG32(HW_REV) & ATI_REV_ID_MASK) >> ATI_REV_ID_SHIFT; 17468c2ecf20Sopenharmony_ci int ret; 17478c2ecf20Sopenharmony_ci 17488c2ecf20Sopenharmony_ci pi = kzalloc(sizeof(struct sumo_power_info), GFP_KERNEL); 17498c2ecf20Sopenharmony_ci if (pi == NULL) 17508c2ecf20Sopenharmony_ci return -ENOMEM; 17518c2ecf20Sopenharmony_ci rdev->pm.dpm.priv = pi; 17528c2ecf20Sopenharmony_ci 17538c2ecf20Sopenharmony_ci pi->driver_nbps_policy_disable = false; 17548c2ecf20Sopenharmony_ci if ((rdev->family == CHIP_PALM) && (hw_rev < 3)) 17558c2ecf20Sopenharmony_ci pi->disable_gfx_power_gating_in_uvd = true; 17568c2ecf20Sopenharmony_ci else 17578c2ecf20Sopenharmony_ci pi->disable_gfx_power_gating_in_uvd = false; 17588c2ecf20Sopenharmony_ci pi->enable_alt_vddnb = true; 17598c2ecf20Sopenharmony_ci pi->enable_sclk_ds = true; 17608c2ecf20Sopenharmony_ci pi->enable_dynamic_m3_arbiter = false; 17618c2ecf20Sopenharmony_ci pi->enable_dynamic_patch_ps = true; 17628c2ecf20Sopenharmony_ci /* Some PALM chips don't seem to properly ungate gfx when UVD is in use; 17638c2ecf20Sopenharmony_ci * for now just disable gfx PG. 17648c2ecf20Sopenharmony_ci */ 17658c2ecf20Sopenharmony_ci if (rdev->family == CHIP_PALM) 17668c2ecf20Sopenharmony_ci pi->enable_gfx_power_gating = false; 17678c2ecf20Sopenharmony_ci else 17688c2ecf20Sopenharmony_ci pi->enable_gfx_power_gating = true; 17698c2ecf20Sopenharmony_ci pi->enable_gfx_clock_gating = true; 17708c2ecf20Sopenharmony_ci pi->enable_mg_clock_gating = true; 17718c2ecf20Sopenharmony_ci pi->enable_auto_thermal_throttling = true; 17728c2ecf20Sopenharmony_ci 17738c2ecf20Sopenharmony_ci ret = sumo_parse_sys_info_table(rdev); 17748c2ecf20Sopenharmony_ci if (ret) 17758c2ecf20Sopenharmony_ci return ret; 17768c2ecf20Sopenharmony_ci 17778c2ecf20Sopenharmony_ci sumo_construct_boot_and_acpi_state(rdev); 17788c2ecf20Sopenharmony_ci 17798c2ecf20Sopenharmony_ci ret = r600_get_platform_caps(rdev); 17808c2ecf20Sopenharmony_ci if (ret) 17818c2ecf20Sopenharmony_ci return ret; 17828c2ecf20Sopenharmony_ci 17838c2ecf20Sopenharmony_ci ret = sumo_parse_power_table(rdev); 17848c2ecf20Sopenharmony_ci if (ret) 17858c2ecf20Sopenharmony_ci return ret; 17868c2ecf20Sopenharmony_ci 17878c2ecf20Sopenharmony_ci pi->pasi = CYPRESS_HASI_DFLT; 17888c2ecf20Sopenharmony_ci pi->asi = RV770_ASI_DFLT; 17898c2ecf20Sopenharmony_ci pi->thermal_auto_throttling = pi->sys_info.htc_tmp_lmt; 17908c2ecf20Sopenharmony_ci pi->enable_boost = pi->sys_info.enable_boost; 17918c2ecf20Sopenharmony_ci pi->enable_dpm = true; 17928c2ecf20Sopenharmony_ci 17938c2ecf20Sopenharmony_ci return 0; 17948c2ecf20Sopenharmony_ci} 17958c2ecf20Sopenharmony_ci 17968c2ecf20Sopenharmony_civoid sumo_dpm_print_power_state(struct radeon_device *rdev, 17978c2ecf20Sopenharmony_ci struct radeon_ps *rps) 17988c2ecf20Sopenharmony_ci{ 17998c2ecf20Sopenharmony_ci int i; 18008c2ecf20Sopenharmony_ci struct sumo_ps *ps = sumo_get_ps(rps); 18018c2ecf20Sopenharmony_ci 18028c2ecf20Sopenharmony_ci r600_dpm_print_class_info(rps->class, rps->class2); 18038c2ecf20Sopenharmony_ci r600_dpm_print_cap_info(rps->caps); 18048c2ecf20Sopenharmony_ci printk("\tuvd vclk: %d dclk: %d\n", rps->vclk, rps->dclk); 18058c2ecf20Sopenharmony_ci for (i = 0; i < ps->num_levels; i++) { 18068c2ecf20Sopenharmony_ci struct sumo_pl *pl = &ps->levels[i]; 18078c2ecf20Sopenharmony_ci printk("\t\tpower level %d sclk: %u vddc: %u\n", 18088c2ecf20Sopenharmony_ci i, pl->sclk, 18098c2ecf20Sopenharmony_ci sumo_convert_voltage_index_to_value(rdev, pl->vddc_index)); 18108c2ecf20Sopenharmony_ci } 18118c2ecf20Sopenharmony_ci r600_dpm_print_ps_status(rdev, rps); 18128c2ecf20Sopenharmony_ci} 18138c2ecf20Sopenharmony_ci 18148c2ecf20Sopenharmony_civoid sumo_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev, 18158c2ecf20Sopenharmony_ci struct seq_file *m) 18168c2ecf20Sopenharmony_ci{ 18178c2ecf20Sopenharmony_ci struct sumo_power_info *pi = sumo_get_pi(rdev); 18188c2ecf20Sopenharmony_ci struct radeon_ps *rps = &pi->current_rps; 18198c2ecf20Sopenharmony_ci struct sumo_ps *ps = sumo_get_ps(rps); 18208c2ecf20Sopenharmony_ci struct sumo_pl *pl; 18218c2ecf20Sopenharmony_ci u32 current_index = 18228c2ecf20Sopenharmony_ci (RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURR_INDEX_MASK) >> 18238c2ecf20Sopenharmony_ci CURR_INDEX_SHIFT; 18248c2ecf20Sopenharmony_ci 18258c2ecf20Sopenharmony_ci if (current_index == BOOST_DPM_LEVEL) { 18268c2ecf20Sopenharmony_ci pl = &pi->boost_pl; 18278c2ecf20Sopenharmony_ci seq_printf(m, "uvd vclk: %d dclk: %d\n", rps->vclk, rps->dclk); 18288c2ecf20Sopenharmony_ci seq_printf(m, "power level %d sclk: %u vddc: %u\n", 18298c2ecf20Sopenharmony_ci current_index, pl->sclk, 18308c2ecf20Sopenharmony_ci sumo_convert_voltage_index_to_value(rdev, pl->vddc_index)); 18318c2ecf20Sopenharmony_ci } else if (current_index >= ps->num_levels) { 18328c2ecf20Sopenharmony_ci seq_printf(m, "invalid dpm profile %d\n", current_index); 18338c2ecf20Sopenharmony_ci } else { 18348c2ecf20Sopenharmony_ci pl = &ps->levels[current_index]; 18358c2ecf20Sopenharmony_ci seq_printf(m, "uvd vclk: %d dclk: %d\n", rps->vclk, rps->dclk); 18368c2ecf20Sopenharmony_ci seq_printf(m, "power level %d sclk: %u vddc: %u\n", 18378c2ecf20Sopenharmony_ci current_index, pl->sclk, 18388c2ecf20Sopenharmony_ci sumo_convert_voltage_index_to_value(rdev, pl->vddc_index)); 18398c2ecf20Sopenharmony_ci } 18408c2ecf20Sopenharmony_ci} 18418c2ecf20Sopenharmony_ci 18428c2ecf20Sopenharmony_ciu32 sumo_dpm_get_current_sclk(struct radeon_device *rdev) 18438c2ecf20Sopenharmony_ci{ 18448c2ecf20Sopenharmony_ci struct sumo_power_info *pi = sumo_get_pi(rdev); 18458c2ecf20Sopenharmony_ci struct radeon_ps *rps = &pi->current_rps; 18468c2ecf20Sopenharmony_ci struct sumo_ps *ps = sumo_get_ps(rps); 18478c2ecf20Sopenharmony_ci struct sumo_pl *pl; 18488c2ecf20Sopenharmony_ci u32 current_index = 18498c2ecf20Sopenharmony_ci (RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURR_INDEX_MASK) >> 18508c2ecf20Sopenharmony_ci CURR_INDEX_SHIFT; 18518c2ecf20Sopenharmony_ci 18528c2ecf20Sopenharmony_ci if (current_index == BOOST_DPM_LEVEL) { 18538c2ecf20Sopenharmony_ci pl = &pi->boost_pl; 18548c2ecf20Sopenharmony_ci return pl->sclk; 18558c2ecf20Sopenharmony_ci } else if (current_index >= ps->num_levels) { 18568c2ecf20Sopenharmony_ci return 0; 18578c2ecf20Sopenharmony_ci } else { 18588c2ecf20Sopenharmony_ci pl = &ps->levels[current_index]; 18598c2ecf20Sopenharmony_ci return pl->sclk; 18608c2ecf20Sopenharmony_ci } 18618c2ecf20Sopenharmony_ci} 18628c2ecf20Sopenharmony_ci 18638c2ecf20Sopenharmony_ciu32 sumo_dpm_get_current_mclk(struct radeon_device *rdev) 18648c2ecf20Sopenharmony_ci{ 18658c2ecf20Sopenharmony_ci struct sumo_power_info *pi = sumo_get_pi(rdev); 18668c2ecf20Sopenharmony_ci 18678c2ecf20Sopenharmony_ci return pi->sys_info.bootup_uma_clk; 18688c2ecf20Sopenharmony_ci} 18698c2ecf20Sopenharmony_ci 18708c2ecf20Sopenharmony_civoid sumo_dpm_fini(struct radeon_device *rdev) 18718c2ecf20Sopenharmony_ci{ 18728c2ecf20Sopenharmony_ci int i; 18738c2ecf20Sopenharmony_ci 18748c2ecf20Sopenharmony_ci sumo_cleanup_asic(rdev); /* ??? */ 18758c2ecf20Sopenharmony_ci 18768c2ecf20Sopenharmony_ci for (i = 0; i < rdev->pm.dpm.num_ps; i++) { 18778c2ecf20Sopenharmony_ci kfree(rdev->pm.dpm.ps[i].ps_priv); 18788c2ecf20Sopenharmony_ci } 18798c2ecf20Sopenharmony_ci kfree(rdev->pm.dpm.ps); 18808c2ecf20Sopenharmony_ci kfree(rdev->pm.dpm.priv); 18818c2ecf20Sopenharmony_ci} 18828c2ecf20Sopenharmony_ci 18838c2ecf20Sopenharmony_ciu32 sumo_dpm_get_sclk(struct radeon_device *rdev, bool low) 18848c2ecf20Sopenharmony_ci{ 18858c2ecf20Sopenharmony_ci struct sumo_power_info *pi = sumo_get_pi(rdev); 18868c2ecf20Sopenharmony_ci struct sumo_ps *requested_state = sumo_get_ps(&pi->requested_rps); 18878c2ecf20Sopenharmony_ci 18888c2ecf20Sopenharmony_ci if (low) 18898c2ecf20Sopenharmony_ci return requested_state->levels[0].sclk; 18908c2ecf20Sopenharmony_ci else 18918c2ecf20Sopenharmony_ci return requested_state->levels[requested_state->num_levels - 1].sclk; 18928c2ecf20Sopenharmony_ci} 18938c2ecf20Sopenharmony_ci 18948c2ecf20Sopenharmony_ciu32 sumo_dpm_get_mclk(struct radeon_device *rdev, bool low) 18958c2ecf20Sopenharmony_ci{ 18968c2ecf20Sopenharmony_ci struct sumo_power_info *pi = sumo_get_pi(rdev); 18978c2ecf20Sopenharmony_ci 18988c2ecf20Sopenharmony_ci return pi->sys_info.bootup_uma_clk; 18998c2ecf20Sopenharmony_ci} 19008c2ecf20Sopenharmony_ci 19018c2ecf20Sopenharmony_ciint sumo_dpm_force_performance_level(struct radeon_device *rdev, 19028c2ecf20Sopenharmony_ci enum radeon_dpm_forced_level level) 19038c2ecf20Sopenharmony_ci{ 19048c2ecf20Sopenharmony_ci struct sumo_power_info *pi = sumo_get_pi(rdev); 19058c2ecf20Sopenharmony_ci struct radeon_ps *rps = &pi->current_rps; 19068c2ecf20Sopenharmony_ci struct sumo_ps *ps = sumo_get_ps(rps); 19078c2ecf20Sopenharmony_ci int i; 19088c2ecf20Sopenharmony_ci 19098c2ecf20Sopenharmony_ci if (ps->num_levels <= 1) 19108c2ecf20Sopenharmony_ci return 0; 19118c2ecf20Sopenharmony_ci 19128c2ecf20Sopenharmony_ci if (level == RADEON_DPM_FORCED_LEVEL_HIGH) { 19138c2ecf20Sopenharmony_ci if (pi->enable_boost) 19148c2ecf20Sopenharmony_ci sumo_enable_boost(rdev, rps, false); 19158c2ecf20Sopenharmony_ci sumo_power_level_enable(rdev, ps->num_levels - 1, true); 19168c2ecf20Sopenharmony_ci sumo_set_forced_level(rdev, ps->num_levels - 1); 19178c2ecf20Sopenharmony_ci sumo_set_forced_mode_enabled(rdev); 19188c2ecf20Sopenharmony_ci for (i = 0; i < ps->num_levels - 1; i++) { 19198c2ecf20Sopenharmony_ci sumo_power_level_enable(rdev, i, false); 19208c2ecf20Sopenharmony_ci } 19218c2ecf20Sopenharmony_ci sumo_set_forced_mode(rdev, false); 19228c2ecf20Sopenharmony_ci sumo_set_forced_mode_enabled(rdev); 19238c2ecf20Sopenharmony_ci sumo_set_forced_mode(rdev, false); 19248c2ecf20Sopenharmony_ci } else if (level == RADEON_DPM_FORCED_LEVEL_LOW) { 19258c2ecf20Sopenharmony_ci if (pi->enable_boost) 19268c2ecf20Sopenharmony_ci sumo_enable_boost(rdev, rps, false); 19278c2ecf20Sopenharmony_ci sumo_power_level_enable(rdev, 0, true); 19288c2ecf20Sopenharmony_ci sumo_set_forced_level(rdev, 0); 19298c2ecf20Sopenharmony_ci sumo_set_forced_mode_enabled(rdev); 19308c2ecf20Sopenharmony_ci for (i = 1; i < ps->num_levels; i++) { 19318c2ecf20Sopenharmony_ci sumo_power_level_enable(rdev, i, false); 19328c2ecf20Sopenharmony_ci } 19338c2ecf20Sopenharmony_ci sumo_set_forced_mode(rdev, false); 19348c2ecf20Sopenharmony_ci sumo_set_forced_mode_enabled(rdev); 19358c2ecf20Sopenharmony_ci sumo_set_forced_mode(rdev, false); 19368c2ecf20Sopenharmony_ci } else { 19378c2ecf20Sopenharmony_ci for (i = 0; i < ps->num_levels; i++) { 19388c2ecf20Sopenharmony_ci sumo_power_level_enable(rdev, i, true); 19398c2ecf20Sopenharmony_ci } 19408c2ecf20Sopenharmony_ci if (pi->enable_boost) 19418c2ecf20Sopenharmony_ci sumo_enable_boost(rdev, rps, true); 19428c2ecf20Sopenharmony_ci } 19438c2ecf20Sopenharmony_ci 19448c2ecf20Sopenharmony_ci rdev->pm.dpm.forced_level = level; 19458c2ecf20Sopenharmony_ci 19468c2ecf20Sopenharmony_ci return 0; 19478c2ecf20Sopenharmony_ci} 1948