1 /* $NetBSD: amdgpu_mes_v10_1.c,v 1.3 2021/12/19 12:02:39 riastradh Exp $ */ 2 3 /* 4 * Copyright 2019 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: amdgpu_mes_v10_1.c,v 1.3 2021/12/19 12:02:39 riastradh Exp $"); 28 29 #include <linux/firmware.h> 30 #include <linux/module.h> 31 #include "amdgpu.h" 32 #include "soc15_common.h" 33 #include "nv.h" 34 #include "gc/gc_10_1_0_offset.h" 35 #include "gc/gc_10_1_0_sh_mask.h" 36 37 MODULE_FIRMWARE("amdgpu/navi10_mes.bin"); 38 39 static int mes_v10_1_add_hw_queue(struct amdgpu_mes *mes, 40 struct mes_add_queue_input *input) 41 { 42 return 0; 43 } 44 45 static int mes_v10_1_remove_hw_queue(struct amdgpu_mes *mes, 46 struct mes_remove_queue_input *input) 47 { 48 return 0; 49 } 50 51 static int mes_v10_1_suspend_gang(struct amdgpu_mes *mes, 52 struct mes_suspend_gang_input *input) 53 { 54 return 0; 55 } 56 57 static int mes_v10_1_resume_gang(struct amdgpu_mes *mes, 58 struct mes_resume_gang_input *input) 59 { 60 return 0; 61 } 62 63 static const struct amdgpu_mes_funcs mes_v10_1_funcs __unused = { 64 .add_hw_queue = mes_v10_1_add_hw_queue, 65 .remove_hw_queue = mes_v10_1_remove_hw_queue, 66 .suspend_gang = mes_v10_1_suspend_gang, 67 .resume_gang = mes_v10_1_resume_gang, 68 }; 69 70 static int mes_v10_1_init_microcode(struct amdgpu_device *adev) 71 { 72 const char *chip_name; 73 char fw_name[30]; 74 int err; 75 const struct mes_firmware_header_v1_0 *mes_hdr; 76 77 switch (adev->asic_type) { 78 case CHIP_NAVI10: 79 chip_name = "navi10"; 80 break; 81 default: 82 BUG(); 83 } 84 85 snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mes.bin", chip_name); 86 err = request_firmware(&adev->mes.fw, fw_name, adev->dev); 87 if (err) 88 return err; 89 90 err = amdgpu_ucode_validate(adev->mes.fw); 91 if (err) { 92 release_firmware(adev->mes.fw); 93 adev->mes.fw = NULL; 94 return err; 95 } 96 97 mes_hdr = (const struct mes_firmware_header_v1_0 *)adev->mes.fw->data; 98 adev->mes.ucode_fw_version = le32_to_cpu(mes_hdr->mes_ucode_version); 99 adev->mes.ucode_fw_version = 100 le32_to_cpu(mes_hdr->mes_ucode_data_version); 101 adev->mes.uc_start_addr = 102 le32_to_cpu(mes_hdr->mes_uc_start_addr_lo) | 103 ((uint64_t)(le32_to_cpu(mes_hdr->mes_uc_start_addr_hi)) << 32); 104 adev->mes.data_start_addr = 105 le32_to_cpu(mes_hdr->mes_data_start_addr_lo) | 106 ((uint64_t)(le32_to_cpu(mes_hdr->mes_data_start_addr_hi)) << 32); 107 108 return 0; 109 } 110 111 static void mes_v10_1_free_microcode(struct amdgpu_device *adev) 112 { 113 release_firmware(adev->mes.fw); 114 adev->mes.fw = NULL; 115 } 116 117 static int mes_v10_1_allocate_ucode_buffer(struct amdgpu_device *adev) 118 { 119 int r; 120 const struct mes_firmware_header_v1_0 *mes_hdr; 121 const __le32 *fw_data; 122 unsigned fw_size; 123 124 mes_hdr = (const struct mes_firmware_header_v1_0 *) 125 adev->mes.fw->data; 126 127 fw_data = (const __le32 *)(adev->mes.fw->data + 128 le32_to_cpu(mes_hdr->mes_ucode_offset_bytes)); 129 fw_size = le32_to_cpu(mes_hdr->mes_ucode_size_bytes); 130 131 r = amdgpu_bo_create_reserved(adev, fw_size, 132 PAGE_SIZE, AMDGPU_GEM_DOMAIN_GTT, 133 &adev->mes.ucode_fw_obj, 134 &adev->mes.ucode_fw_gpu_addr, 135 (void **)&adev->mes.ucode_fw_ptr); 136 if (r) { 137 dev_err(adev->dev, "(%d) failed to create mes fw bo\n", r); 138 return r; 139 } 140 141 memcpy(adev->mes.ucode_fw_ptr, fw_data, fw_size); 142 143 amdgpu_bo_kunmap(adev->mes.ucode_fw_obj); 144 amdgpu_bo_unreserve(adev->mes.ucode_fw_obj); 145 146 return 0; 147 } 148 149 static int mes_v10_1_allocate_ucode_data_buffer(struct amdgpu_device *adev) 150 { 151 int r; 152 const struct mes_firmware_header_v1_0 *mes_hdr; 153 const __le32 *fw_data; 154 unsigned fw_size; 155 156 mes_hdr = (const struct mes_firmware_header_v1_0 *) 157 adev->mes.fw->data; 158 159 fw_data = (const __le32 *)(adev->mes.fw->data + 160 le32_to_cpu(mes_hdr->mes_ucode_data_offset_bytes)); 161 fw_size = le32_to_cpu(mes_hdr->mes_ucode_data_size_bytes); 162 163 r = amdgpu_bo_create_reserved(adev, fw_size, 164 64 * 1024, AMDGPU_GEM_DOMAIN_GTT, 165 &adev->mes.data_fw_obj, 166 &adev->mes.data_fw_gpu_addr, 167 (void **)&adev->mes.data_fw_ptr); 168 if (r) { 169 dev_err(adev->dev, "(%d) failed to create mes data fw bo\n", r); 170 return r; 171 } 172 173 memcpy(adev->mes.data_fw_ptr, fw_data, fw_size); 174 175 amdgpu_bo_kunmap(adev->mes.data_fw_obj); 176 amdgpu_bo_unreserve(adev->mes.data_fw_obj); 177 178 return 0; 179 } 180 181 static void mes_v10_1_free_ucode_buffers(struct amdgpu_device *adev) 182 { 183 amdgpu_bo_free_kernel(&adev->mes.data_fw_obj, 184 &adev->mes.data_fw_gpu_addr, 185 (void **)&adev->mes.data_fw_ptr); 186 187 amdgpu_bo_free_kernel(&adev->mes.ucode_fw_obj, 188 &adev->mes.ucode_fw_gpu_addr, 189 (void **)&adev->mes.ucode_fw_ptr); 190 } 191 192 static void mes_v10_1_enable(struct amdgpu_device *adev, bool enable) 193 { 194 uint32_t data = 0; 195 196 if (enable) { 197 data = RREG32_SOC15(GC, 0, mmCP_MES_CNTL); 198 data = REG_SET_FIELD(data, CP_MES_CNTL, MES_PIPE0_RESET, 1); 199 WREG32_SOC15(GC, 0, mmCP_MES_CNTL, data); 200 201 /* set ucode start address */ 202 WREG32_SOC15(GC, 0, mmCP_MES_PRGRM_CNTR_START, 203 (uint32_t)(adev->mes.uc_start_addr) >> 2); 204 205 /* clear BYPASS_UNCACHED to avoid hangs after interrupt. */ 206 data = RREG32_SOC15(GC, 0, mmCP_MES_DC_OP_CNTL); 207 data = REG_SET_FIELD(data, CP_MES_DC_OP_CNTL, 208 BYPASS_UNCACHED, 0); 209 WREG32_SOC15(GC, 0, mmCP_MES_DC_OP_CNTL, data); 210 211 /* unhalt MES and activate pipe0 */ 212 data = REG_SET_FIELD(0, CP_MES_CNTL, MES_PIPE0_ACTIVE, 1); 213 WREG32_SOC15(GC, 0, mmCP_MES_CNTL, data); 214 } else { 215 data = RREG32_SOC15(GC, 0, mmCP_MES_CNTL); 216 data = REG_SET_FIELD(data, CP_MES_CNTL, MES_PIPE0_ACTIVE, 0); 217 data = REG_SET_FIELD(data, CP_MES_CNTL, 218 MES_INVALIDATE_ICACHE, 1); 219 data = REG_SET_FIELD(data, CP_MES_CNTL, MES_PIPE0_RESET, 1); 220 data = REG_SET_FIELD(data, CP_MES_CNTL, MES_HALT, 1); 221 WREG32_SOC15(GC, 0, mmCP_MES_CNTL, data); 222 } 223 } 224 225 /* This function is for backdoor MES firmware */ 226 static int mes_v10_1_load_microcode(struct amdgpu_device *adev) 227 { 228 int r; 229 uint32_t data; 230 231 if (!adev->mes.fw) 232 return -EINVAL; 233 234 r = mes_v10_1_allocate_ucode_buffer(adev); 235 if (r) 236 return r; 237 238 r = mes_v10_1_allocate_ucode_data_buffer(adev); 239 if (r) { 240 mes_v10_1_free_ucode_buffers(adev); 241 return r; 242 } 243 244 mes_v10_1_enable(adev, false); 245 246 WREG32_SOC15(GC, 0, mmCP_MES_IC_BASE_CNTL, 0); 247 248 mutex_lock(&adev->srbm_mutex); 249 /* me=3, pipe=0, queue=0 */ 250 nv_grbm_select(adev, 3, 0, 0, 0); 251 252 /* set ucode start address */ 253 WREG32_SOC15(GC, 0, mmCP_MES_PRGRM_CNTR_START, 254 (uint32_t)(adev->mes.uc_start_addr) >> 2); 255 256 /* set ucode fimrware address */ 257 WREG32_SOC15(GC, 0, mmCP_MES_IC_BASE_LO, 258 lower_32_bits(adev->mes.ucode_fw_gpu_addr)); 259 WREG32_SOC15(GC, 0, mmCP_MES_IC_BASE_HI, 260 upper_32_bits(adev->mes.ucode_fw_gpu_addr)); 261 262 /* set ucode instruction cache boundary to 2M-1 */ 263 WREG32_SOC15(GC, 0, mmCP_MES_MIBOUND_LO, 0x1FFFFF); 264 265 /* set ucode data firmware address */ 266 WREG32_SOC15(GC, 0, mmCP_MES_MDBASE_LO, 267 lower_32_bits(adev->mes.data_fw_gpu_addr)); 268 WREG32_SOC15(GC, 0, mmCP_MES_MDBASE_HI, 269 upper_32_bits(adev->mes.data_fw_gpu_addr)); 270 271 /* Set 0x3FFFF (256K-1) to CP_MES_MDBOUND_LO */ 272 WREG32_SOC15(GC, 0, mmCP_MES_MDBOUND_LO, 0x3FFFF); 273 274 /* invalidate ICACHE */ 275 data = RREG32_SOC15(GC, 0, mmCP_MES_IC_OP_CNTL); 276 data = REG_SET_FIELD(data, CP_MES_IC_OP_CNTL, PRIME_ICACHE, 0); 277 data = REG_SET_FIELD(data, CP_MES_IC_OP_CNTL, INVALIDATE_CACHE, 1); 278 WREG32_SOC15(GC, 0, mmCP_MES_IC_OP_CNTL, data); 279 280 /* prime the ICACHE. */ 281 data = RREG32_SOC15(GC, 0, mmCP_MES_IC_OP_CNTL); 282 data = REG_SET_FIELD(data, CP_MES_IC_OP_CNTL, PRIME_ICACHE, 1); 283 WREG32_SOC15(GC, 0, mmCP_MES_IC_OP_CNTL, data); 284 285 nv_grbm_select(adev, 0, 0, 0, 0); 286 mutex_unlock(&adev->srbm_mutex); 287 288 return 0; 289 } 290 291 static int mes_v10_1_sw_init(void *handle) 292 { 293 int r; 294 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 295 296 r = mes_v10_1_init_microcode(adev); 297 if (r) 298 return r; 299 300 return 0; 301 } 302 303 static int mes_v10_1_sw_fini(void *handle) 304 { 305 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 306 307 mes_v10_1_free_microcode(adev); 308 309 return 0; 310 } 311 312 static int mes_v10_1_hw_init(void *handle) 313 { 314 int r; 315 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 316 317 if (adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT) { 318 r = mes_v10_1_load_microcode(adev); 319 if (r) { 320 DRM_ERROR("failed to MES fw, r=%d\n", r); 321 return r; 322 } 323 } else { 324 DRM_ERROR("only support direct fw loading on MES\n"); 325 return -EINVAL; 326 } 327 328 mes_v10_1_enable(adev, true); 329 330 return 0; 331 } 332 333 static int mes_v10_1_hw_fini(void *handle) 334 { 335 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 336 337 mes_v10_1_enable(adev, false); 338 339 if (adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT) 340 mes_v10_1_free_ucode_buffers(adev); 341 342 return 0; 343 } 344 345 static int mes_v10_1_suspend(void *handle) 346 { 347 return 0; 348 } 349 350 static int mes_v10_1_resume(void *handle) 351 { 352 return 0; 353 } 354 355 static const struct amd_ip_funcs mes_v10_1_ip_funcs = { 356 .name = "mes_v10_1", 357 .sw_init = mes_v10_1_sw_init, 358 .sw_fini = mes_v10_1_sw_fini, 359 .hw_init = mes_v10_1_hw_init, 360 .hw_fini = mes_v10_1_hw_fini, 361 .suspend = mes_v10_1_suspend, 362 .resume = mes_v10_1_resume, 363 }; 364 365 const struct amdgpu_ip_block_version mes_v10_1_ip_block = { 366 .type = AMD_IP_BLOCK_TYPE_MES, 367 .major = 10, 368 .minor = 1, 369 .rev = 0, 370 .funcs = &mes_v10_1_ip_funcs, 371 }; 372