1/* $NetBSD: radeon_sumo_smc.c,v 1.2 2021/12/18 23:45:43 riastradh Exp $ */ 2 3/* 4 * Copyright 2012 Advanced Micro Devices, Inc. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 * OTHER DEALINGS IN THE SOFTWARE. 23 * 24 */ 25 26#include <sys/cdefs.h> 27__KERNEL_RCSID(0, "$NetBSD: radeon_sumo_smc.c,v 1.2 2021/12/18 23:45:43 riastradh Exp $"); 28 29#include "radeon.h" 30#include "sumod.h" 31#include "sumo_dpm.h" 32#include "ppsmc.h" 33 34#define SUMO_SMU_SERVICE_ROUTINE_PG_INIT 1 35#define SUMO_SMU_SERVICE_ROUTINE_ALTVDDNB_NOTIFY 27 36#define SUMO_SMU_SERVICE_ROUTINE_GFX_SRV_ID_20 20 37 38struct sumo_power_info *sumo_get_pi(struct radeon_device *rdev); 39 40static void sumo_send_msg_to_smu(struct radeon_device *rdev, u32 id) 41{ 42 u32 gfx_int_req; 43 int i; 44 45 for (i = 0; i < rdev->usec_timeout; i++) { 46 if (RREG32(GFX_INT_STATUS) & INT_DONE) 47 break; 48 udelay(1); 49 } 50 51 gfx_int_req = SERV_INDEX(id) | INT_REQ; 52 WREG32(GFX_INT_REQ, gfx_int_req); 53 54 for (i = 0; i < rdev->usec_timeout; i++) { 55 if (RREG32(GFX_INT_REQ) & INT_REQ) 56 break; 57 udelay(1); 58 } 59 60 for (i = 0; i < rdev->usec_timeout; i++) { 61 if (RREG32(GFX_INT_STATUS) & INT_ACK) 62 break; 63 udelay(1); 64 } 65 66 for (i = 0; i < rdev->usec_timeout; i++) { 67 if (RREG32(GFX_INT_STATUS) & INT_DONE) 68 break; 69 udelay(1); 70 } 71 72 gfx_int_req &= ~INT_REQ; 73 WREG32(GFX_INT_REQ, gfx_int_req); 74} 75 76void sumo_initialize_m3_arb(struct radeon_device *rdev) 77{ 78 struct sumo_power_info *pi = sumo_get_pi(rdev); 79 u32 i; 80 81 if (!pi->enable_dynamic_m3_arbiter) 82 return; 83 84 for (i = 0; i < NUMBER_OF_M3ARB_PARAM_SETS; i++) 85 WREG32_RCU(MCU_M3ARB_PARAMS + (i * 4), 86 pi->sys_info.csr_m3_arb_cntl_default[i]); 87 88 for (; i < NUMBER_OF_M3ARB_PARAM_SETS * 2; i++) 89 WREG32_RCU(MCU_M3ARB_PARAMS + (i * 4), 90 pi->sys_info.csr_m3_arb_cntl_uvd[i % NUMBER_OF_M3ARB_PARAM_SETS]); 91 92 for (; i < NUMBER_OF_M3ARB_PARAM_SETS * 3; i++) 93 WREG32_RCU(MCU_M3ARB_PARAMS + (i * 4), 94 pi->sys_info.csr_m3_arb_cntl_fs3d[i % NUMBER_OF_M3ARB_PARAM_SETS]); 95} 96 97static bool sumo_is_alt_vddnb_supported(struct radeon_device *rdev) 98{ 99 struct sumo_power_info *pi = sumo_get_pi(rdev); 100 bool return_code = false; 101 102 if (!pi->enable_alt_vddnb) 103 return return_code; 104 105 if ((rdev->family == CHIP_SUMO) || (rdev->family == CHIP_SUMO2)) { 106 if (pi->fw_version >= 0x00010C00) 107 return_code = true; 108 } 109 110 return return_code; 111} 112 113void sumo_smu_notify_alt_vddnb_change(struct radeon_device *rdev, 114 bool powersaving, bool force_nbps1) 115{ 116 u32 param = 0; 117 118 if (!sumo_is_alt_vddnb_supported(rdev)) 119 return; 120 121 if (powersaving) 122 param |= 1; 123 124 if (force_nbps1) 125 param |= 2; 126 127 WREG32_RCU(RCU_ALTVDDNB_NOTIFY, param); 128 129 sumo_send_msg_to_smu(rdev, SUMO_SMU_SERVICE_ROUTINE_ALTVDDNB_NOTIFY); 130} 131 132void sumo_smu_pg_init(struct radeon_device *rdev) 133{ 134 sumo_send_msg_to_smu(rdev, SUMO_SMU_SERVICE_ROUTINE_PG_INIT); 135} 136 137static u32 sumo_power_of_4(u32 unit) 138{ 139 u32 ret = 1; 140 u32 i; 141 142 for (i = 0; i < unit; i++) 143 ret *= 4; 144 145 return ret; 146} 147 148void sumo_enable_boost_timer(struct radeon_device *rdev) 149{ 150 struct sumo_power_info *pi = sumo_get_pi(rdev); 151 u32 period, unit, timer_value; 152 u32 xclk = radeon_get_xclk(rdev); 153 154 unit = (RREG32_RCU(RCU_LCLK_SCALING_CNTL) & LCLK_SCALING_TIMER_PRESCALER_MASK) 155 >> LCLK_SCALING_TIMER_PRESCALER_SHIFT; 156 157 period = 100 * (xclk / 100 / sumo_power_of_4(unit)); 158 159 timer_value = (period << 16) | (unit << 4); 160 161 WREG32_RCU(RCU_GNB_PWR_REP_TIMER_CNTL, timer_value); 162 WREG32_RCU(RCU_BOOST_MARGIN, pi->sys_info.sclk_dpm_boost_margin); 163 WREG32_RCU(RCU_THROTTLE_MARGIN, pi->sys_info.sclk_dpm_throttle_margin); 164 WREG32_RCU(GNB_TDP_LIMIT, pi->sys_info.gnb_tdp_limit); 165 WREG32_RCU(RCU_SclkDpmTdpLimitPG, pi->sys_info.sclk_dpm_tdp_limit_pg); 166 167 sumo_send_msg_to_smu(rdev, SUMO_SMU_SERVICE_ROUTINE_GFX_SRV_ID_20); 168} 169 170void sumo_set_tdp_limit(struct radeon_device *rdev, u32 index, u32 tdp_limit) 171{ 172 u32 regoffset = 0; 173 u32 shift = 0; 174 u32 mask = 0xFFF; 175 u32 sclk_dpm_tdp_limit; 176 177 switch (index) { 178 case 0: 179 regoffset = RCU_SclkDpmTdpLimit01; 180 shift = 16; 181 break; 182 case 1: 183 regoffset = RCU_SclkDpmTdpLimit01; 184 shift = 0; 185 break; 186 case 2: 187 regoffset = RCU_SclkDpmTdpLimit23; 188 shift = 16; 189 break; 190 case 3: 191 regoffset = RCU_SclkDpmTdpLimit23; 192 shift = 0; 193 break; 194 case 4: 195 regoffset = RCU_SclkDpmTdpLimit47; 196 shift = 16; 197 break; 198 case 7: 199 regoffset = RCU_SclkDpmTdpLimit47; 200 shift = 0; 201 break; 202 default: 203 break; 204 } 205 206 sclk_dpm_tdp_limit = RREG32_RCU(regoffset); 207 sclk_dpm_tdp_limit &= ~(mask << shift); 208 sclk_dpm_tdp_limit |= (tdp_limit << shift); 209 WREG32_RCU(regoffset, sclk_dpm_tdp_limit); 210} 211 212void sumo_boost_state_enable(struct radeon_device *rdev, bool enable) 213{ 214 u32 boost_disable = RREG32_RCU(RCU_GPU_BOOST_DISABLE); 215 216 boost_disable &= 0xFFFFFFFE; 217 boost_disable |= (enable ? 0 : 1); 218 WREG32_RCU(RCU_GPU_BOOST_DISABLE, boost_disable); 219} 220 221u32 sumo_get_running_fw_version(struct radeon_device *rdev) 222{ 223 return RREG32_RCU(RCU_FW_VERSION); 224} 225 226