Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.9-rc2 219 lines 5.1 kB view raw
1/* 2 * Copyright 2013 Advanced Micro Devices, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 * 22 * Authors: Alex Deucher 23 */ 24 25#include "drmP.h" 26#include "amdgpu.h" 27#include "cikd.h" 28#include "kv_dpm.h" 29 30#include "smu/smu_7_0_0_d.h" 31#include "smu/smu_7_0_0_sh_mask.h" 32 33int amdgpu_kv_notify_message_to_smu(struct amdgpu_device *adev, u32 id) 34{ 35 u32 i; 36 u32 tmp = 0; 37 38 WREG32(mmSMC_MESSAGE_0, id & SMC_MESSAGE_0__SMC_MSG_MASK); 39 40 for (i = 0; i < adev->usec_timeout; i++) { 41 if ((RREG32(mmSMC_RESP_0) & SMC_RESP_0__SMC_RESP_MASK) != 0) 42 break; 43 udelay(1); 44 } 45 tmp = RREG32(mmSMC_RESP_0) & SMC_RESP_0__SMC_RESP_MASK; 46 47 if (tmp != 1) { 48 if (tmp == 0xFF) 49 return -EINVAL; 50 else if (tmp == 0xFE) 51 return -EINVAL; 52 } 53 54 return 0; 55} 56 57int amdgpu_kv_dpm_get_enable_mask(struct amdgpu_device *adev, u32 *enable_mask) 58{ 59 int ret; 60 61 ret = amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_SCLKDPM_GetEnabledMask); 62 63 if (ret == 0) 64 *enable_mask = RREG32_SMC(ixSMC_SYSCON_MSG_ARG_0); 65 66 return ret; 67} 68 69int amdgpu_kv_send_msg_to_smc_with_parameter(struct amdgpu_device *adev, 70 PPSMC_Msg msg, u32 parameter) 71{ 72 73 WREG32(mmSMC_MSG_ARG_0, parameter); 74 75 return amdgpu_kv_notify_message_to_smu(adev, msg); 76} 77 78static int kv_set_smc_sram_address(struct amdgpu_device *adev, 79 u32 smc_address, u32 limit) 80{ 81 if (smc_address & 3) 82 return -EINVAL; 83 if ((smc_address + 3) > limit) 84 return -EINVAL; 85 86 WREG32(mmSMC_IND_INDEX_0, smc_address); 87 WREG32_P(mmSMC_IND_ACCESS_CNTL, 0, 88 ~SMC_IND_ACCESS_CNTL__AUTO_INCREMENT_IND_0_MASK); 89 90 return 0; 91} 92 93int amdgpu_kv_read_smc_sram_dword(struct amdgpu_device *adev, u32 smc_address, 94 u32 *value, u32 limit) 95{ 96 int ret; 97 98 ret = kv_set_smc_sram_address(adev, smc_address, limit); 99 if (ret) 100 return ret; 101 102 *value = RREG32(mmSMC_IND_DATA_0); 103 return 0; 104} 105 106int amdgpu_kv_smc_dpm_enable(struct amdgpu_device *adev, bool enable) 107{ 108 if (enable) 109 return amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_DPM_Enable); 110 else 111 return amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_DPM_Disable); 112} 113 114int amdgpu_kv_smc_bapm_enable(struct amdgpu_device *adev, bool enable) 115{ 116 if (enable) 117 return amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_EnableBAPM); 118 else 119 return amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_DisableBAPM); 120} 121 122int amdgpu_kv_copy_bytes_to_smc(struct amdgpu_device *adev, 123 u32 smc_start_address, 124 const u8 *src, u32 byte_count, u32 limit) 125{ 126 int ret; 127 u32 data, original_data, addr, extra_shift, t_byte, count, mask; 128 129 if ((smc_start_address + byte_count) > limit) 130 return -EINVAL; 131 132 addr = smc_start_address; 133 t_byte = addr & 3; 134 135 /* RMW for the initial bytes */ 136 if (t_byte != 0) { 137 addr -= t_byte; 138 139 ret = kv_set_smc_sram_address(adev, addr, limit); 140 if (ret) 141 return ret; 142 143 original_data = RREG32(mmSMC_IND_DATA_0); 144 145 data = 0; 146 mask = 0; 147 count = 4; 148 while (count > 0) { 149 if (t_byte > 0) { 150 mask = (mask << 8) | 0xff; 151 t_byte--; 152 } else if (byte_count > 0) { 153 data = (data << 8) + *src++; 154 byte_count--; 155 mask <<= 8; 156 } else { 157 data <<= 8; 158 mask = (mask << 8) | 0xff; 159 } 160 count--; 161 } 162 163 data |= original_data & mask; 164 165 ret = kv_set_smc_sram_address(adev, addr, limit); 166 if (ret) 167 return ret; 168 169 WREG32(mmSMC_IND_DATA_0, data); 170 171 addr += 4; 172 } 173 174 while (byte_count >= 4) { 175 /* SMC address space is BE */ 176 data = (src[0] << 24) + (src[1] << 16) + (src[2] << 8) + src[3]; 177 178 ret = kv_set_smc_sram_address(adev, addr, limit); 179 if (ret) 180 return ret; 181 182 WREG32(mmSMC_IND_DATA_0, data); 183 184 src += 4; 185 byte_count -= 4; 186 addr += 4; 187 } 188 189 /* RMW for the final bytes */ 190 if (byte_count > 0) { 191 data = 0; 192 193 ret = kv_set_smc_sram_address(adev, addr, limit); 194 if (ret) 195 return ret; 196 197 original_data = RREG32(mmSMC_IND_DATA_0); 198 199 extra_shift = 8 * (4 - byte_count); 200 201 while (byte_count > 0) { 202 /* SMC address space is BE */ 203 data = (data << 8) + *src++; 204 byte_count--; 205 } 206 207 data <<= extra_shift; 208 209 data |= (original_data & ~((~0UL) << extra_shift)); 210 211 ret = kv_set_smc_sram_address(adev, addr, limit); 212 if (ret) 213 return ret; 214 215 WREG32(mmSMC_IND_DATA_0, data); 216 } 217 return 0; 218} 219