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

drm/amdgpu: add PSP driver for vega10 (v2)

PSP is responsible for firmware loading on SOC-15 asics.

v2: fix memory leak (Ken)

Acked-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Huang Rui <ray.huang@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Huang Rui and committed by
Alex Deucher
0e5ca0d1 c1dc356a

+1450
+5
drivers/gpu/drm/amd/amdgpu/Makefile
··· 51 51 cz_ih.o \ 52 52 vega10_ih.o 53 53 54 + # add PSP block 55 + amdgpu-y += \ 56 + amdgpu_psp.o \ 57 + psp_v3_1.o 58 + 54 59 # add SMC block 55 60 amdgpu-y += \ 56 61 amdgpu_dpm.o \
+9
drivers/gpu/drm/amd/amdgpu/amdgpu.h
··· 52 52 #include "amdgpu_irq.h" 53 53 #include "amdgpu_ucode.h" 54 54 #include "amdgpu_ttm.h" 55 + #include "amdgpu_psp.h" 55 56 #include "amdgpu_gds.h" 56 57 #include "amdgpu_sync.h" 57 58 #include "amdgpu_ring.h" ··· 1214 1213 struct amdgpu_bo *fw_buf; 1215 1214 unsigned int fw_size; 1216 1215 unsigned int max_ucodes; 1216 + /* firmwares are loaded by psp instead of smu from vega10 */ 1217 + const struct amdgpu_psp_funcs *funcs; 1218 + struct amdgpu_bo *rbuf; 1219 + struct mutex mutex; 1217 1220 }; 1218 1221 1219 1222 /* ··· 1576 1571 /* firmwares */ 1577 1572 struct amdgpu_firmware firmware; 1578 1573 1574 + /* PSP */ 1575 + struct psp_context psp; 1576 + 1579 1577 /* GDS */ 1580 1578 struct amdgpu_gds gds; 1581 1579 ··· 1833 1825 #define amdgpu_gfx_get_gpu_clock_counter(adev) (adev)->gfx.funcs->get_gpu_clock_counter((adev)) 1834 1826 #define amdgpu_gfx_select_se_sh(adev, se, sh, instance) (adev)->gfx.funcs->select_se_sh((adev), (se), (sh), (instance)) 1835 1827 #define amdgpu_gds_switch(adev, r, v, d, w, a) (adev)->gds.funcs->patch_gds_switch((r), (v), (d), (w), (a)) 1828 + #define amdgpu_psp_check_fw_loading_status(adev, i) (adev)->firmware.funcs->check_fw_loading_status((adev), (i)) 1836 1829 1837 1830 /* Common functions */ 1838 1831 int amdgpu_gpu_reset(struct amdgpu_device *adev);
+1
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
··· 1837 1837 * can recall function without having locking issues */ 1838 1838 mutex_init(&adev->vm_manager.lock); 1839 1839 atomic_set(&adev->irq.ih.lock, 0); 1840 + mutex_init(&adev->firmware.mutex); 1840 1841 mutex_init(&adev->pm.mutex); 1841 1842 mutex_init(&adev->gfx.gpu_clock_mutex); 1842 1843 mutex_init(&adev->srbm_mutex);
+481
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
··· 1 + /* 2 + * Copyright 2016 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 + * Author: Huang Rui 23 + * 24 + */ 25 + 26 + #include <linux/firmware.h> 27 + #include "drmP.h" 28 + #include "amdgpu.h" 29 + #include "amdgpu_psp.h" 30 + #include "amdgpu_ucode.h" 31 + #include "soc15_common.h" 32 + #include "psp_v3_1.h" 33 + 34 + static void psp_set_funcs(struct amdgpu_device *adev); 35 + 36 + static int psp_early_init(void *handle) 37 + { 38 + struct amdgpu_device *adev = (struct amdgpu_device *)handle; 39 + 40 + psp_set_funcs(adev); 41 + 42 + return 0; 43 + } 44 + 45 + static int psp_sw_init(void *handle) 46 + { 47 + struct amdgpu_device *adev = (struct amdgpu_device *)handle; 48 + struct psp_context *psp = &adev->psp; 49 + int ret; 50 + 51 + switch (adev->asic_type) { 52 + case CHIP_VEGA10: 53 + psp->init_microcode = psp_v3_1_init_microcode; 54 + psp->bootloader_load_sysdrv = psp_v3_1_bootloader_load_sysdrv; 55 + psp->bootloader_load_sos = psp_v3_1_bootloader_load_sos; 56 + psp->prep_cmd_buf = psp_v3_1_prep_cmd_buf; 57 + psp->ring_init = psp_v3_1_ring_init; 58 + psp->cmd_submit = psp_v3_1_cmd_submit; 59 + psp->compare_sram_data = psp_v3_1_compare_sram_data; 60 + psp->smu_reload_quirk = psp_v3_1_smu_reload_quirk; 61 + break; 62 + default: 63 + return -EINVAL; 64 + } 65 + 66 + psp->adev = adev; 67 + 68 + ret = psp_init_microcode(psp); 69 + if (ret) { 70 + DRM_ERROR("Failed to load psp firmware!\n"); 71 + return ret; 72 + } 73 + 74 + return 0; 75 + } 76 + 77 + static int psp_sw_fini(void *handle) 78 + { 79 + return 0; 80 + } 81 + 82 + int psp_wait_for(struct psp_context *psp, uint32_t reg_index, 83 + uint32_t reg_val, uint32_t mask, bool check_changed) 84 + { 85 + uint32_t val; 86 + int i; 87 + struct amdgpu_device *adev = psp->adev; 88 + 89 + val = RREG32(reg_index); 90 + 91 + for (i = 0; i < adev->usec_timeout; i++) { 92 + if (check_changed) { 93 + if (val != reg_val) 94 + return 0; 95 + } else { 96 + if ((val & mask) == reg_val) 97 + return 0; 98 + } 99 + udelay(1); 100 + } 101 + 102 + return -ETIME; 103 + } 104 + 105 + static int 106 + psp_cmd_submit_buf(struct psp_context *psp, 107 + struct amdgpu_firmware_info *ucode, 108 + struct psp_gfx_cmd_resp *cmd, uint64_t fence_mc_addr, 109 + int index) 110 + { 111 + int ret; 112 + struct amdgpu_bo *cmd_buf_bo; 113 + uint64_t cmd_buf_mc_addr; 114 + struct psp_gfx_cmd_resp *cmd_buf_mem; 115 + struct amdgpu_device *adev = psp->adev; 116 + 117 + ret = amdgpu_bo_create_kernel(adev, PSP_CMD_BUFFER_SIZE, PAGE_SIZE, 118 + AMDGPU_GEM_DOMAIN_VRAM, 119 + &cmd_buf_bo, &cmd_buf_mc_addr, 120 + (void **)&cmd_buf_mem); 121 + if (ret) 122 + return ret; 123 + 124 + memset(cmd_buf_mem, 0, PSP_CMD_BUFFER_SIZE); 125 + 126 + memcpy(cmd_buf_mem, cmd, sizeof(struct psp_gfx_cmd_resp)); 127 + 128 + ret = psp_cmd_submit(psp, ucode, cmd_buf_mc_addr, 129 + fence_mc_addr, index); 130 + 131 + while (*((unsigned int *)psp->fence_buf) != index) { 132 + msleep(1); 133 + }; 134 + 135 + amdgpu_bo_free_kernel(&cmd_buf_bo, 136 + &cmd_buf_mc_addr, 137 + (void **)&cmd_buf_mem); 138 + 139 + return ret; 140 + } 141 + 142 + static void psp_prep_tmr_cmd_buf(struct psp_gfx_cmd_resp *cmd, 143 + uint64_t tmr_mc, uint32_t size) 144 + { 145 + cmd->cmd_id = GFX_CMD_ID_SETUP_TMR; 146 + cmd->cmd.cmd_setup_tmr.buf_phy_addr_lo = (uint32_t)tmr_mc; 147 + cmd->cmd.cmd_setup_tmr.buf_phy_addr_hi = (uint32_t)(tmr_mc >> 32); 148 + cmd->cmd.cmd_setup_tmr.buf_size = size; 149 + } 150 + 151 + /* Set up Trusted Memory Region */ 152 + static int psp_tmr_init(struct psp_context *psp) 153 + { 154 + int ret; 155 + struct psp_gfx_cmd_resp *cmd; 156 + 157 + cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); 158 + if (!cmd) 159 + return -ENOMEM; 160 + 161 + /* 162 + * Allocate 3M memory aligned to 1M from Frame Buffer (local 163 + * physical). 164 + * 165 + * Note: this memory need be reserved till the driver 166 + * uninitializes. 167 + */ 168 + ret = amdgpu_bo_create_kernel(psp->adev, 0x300000, 0x100000, 169 + AMDGPU_GEM_DOMAIN_VRAM, 170 + &psp->tmr_bo, &psp->tmr_mc_addr, &psp->tmr_buf); 171 + if (ret) 172 + goto failed; 173 + 174 + psp_prep_tmr_cmd_buf(cmd, psp->tmr_mc_addr, 0x300000); 175 + 176 + ret = psp_cmd_submit_buf(psp, NULL, cmd, 177 + psp->fence_buf_mc_addr, 1); 178 + if (ret) 179 + goto failed_mem; 180 + 181 + kfree(cmd); 182 + 183 + return 0; 184 + 185 + failed_mem: 186 + amdgpu_bo_free_kernel(&psp->tmr_bo, &psp->tmr_mc_addr, &psp->tmr_buf); 187 + failed: 188 + kfree(cmd); 189 + return ret; 190 + } 191 + 192 + static void psp_prep_asd_cmd_buf(struct psp_gfx_cmd_resp *cmd, 193 + uint64_t asd_mc, uint64_t asd_mc_shared, 194 + uint32_t size, uint32_t shared_size) 195 + { 196 + cmd->cmd_id = GFX_CMD_ID_LOAD_ASD; 197 + cmd->cmd.cmd_load_ta.app_phy_addr_lo = lower_32_bits(asd_mc); 198 + cmd->cmd.cmd_load_ta.app_phy_addr_hi = upper_32_bits(asd_mc); 199 + cmd->cmd.cmd_load_ta.app_len = size; 200 + 201 + cmd->cmd.cmd_load_ta.cmd_buf_phy_addr_lo = lower_32_bits(asd_mc_shared); 202 + cmd->cmd.cmd_load_ta.cmd_buf_phy_addr_hi = upper_32_bits(asd_mc_shared); 203 + cmd->cmd.cmd_load_ta.cmd_buf_len = shared_size; 204 + } 205 + 206 + static int psp_asd_load(struct psp_context *psp) 207 + { 208 + int ret; 209 + struct amdgpu_bo *asd_bo, *asd_shared_bo; 210 + uint64_t asd_mc_addr, asd_shared_mc_addr; 211 + void *asd_buf, *asd_shared_buf; 212 + struct psp_gfx_cmd_resp *cmd; 213 + 214 + cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); 215 + if (!cmd) 216 + return -ENOMEM; 217 + 218 + /* 219 + * Allocate 16k memory aligned to 4k from Frame Buffer (local 220 + * physical) for shared ASD <-> Driver 221 + */ 222 + ret = amdgpu_bo_create_kernel(psp->adev, PSP_ASD_SHARED_MEM_SIZE, PAGE_SIZE, 223 + AMDGPU_GEM_DOMAIN_VRAM, 224 + &asd_shared_bo, &asd_shared_mc_addr, &asd_buf); 225 + if (ret) 226 + goto failed; 227 + 228 + /* 229 + * Allocate 256k memory aligned to 4k from Frame Buffer (local 230 + * physical) for ASD firmware 231 + */ 232 + ret = amdgpu_bo_create_kernel(psp->adev, PSP_ASD_BIN_SIZE, PAGE_SIZE, 233 + AMDGPU_GEM_DOMAIN_VRAM, 234 + &asd_bo, &asd_mc_addr, &asd_buf); 235 + if (ret) 236 + goto failed_mem; 237 + 238 + memcpy(asd_buf, psp->asd_start_addr, psp->asd_ucode_size); 239 + 240 + psp_prep_asd_cmd_buf(cmd, asd_mc_addr, asd_shared_mc_addr, 241 + psp->asd_ucode_size, PSP_ASD_SHARED_MEM_SIZE); 242 + 243 + ret = psp_cmd_submit_buf(psp, NULL, cmd, 244 + psp->fence_buf_mc_addr, 2); 245 + if (ret) 246 + goto failed_mem1; 247 + 248 + amdgpu_bo_free_kernel(&asd_bo, &asd_mc_addr, &asd_buf); 249 + amdgpu_bo_free_kernel(&asd_shared_bo, &asd_shared_mc_addr, &asd_shared_buf); 250 + kfree(cmd); 251 + 252 + return 0; 253 + 254 + failed_mem1: 255 + amdgpu_bo_free_kernel(&asd_bo, &asd_mc_addr, &asd_buf); 256 + failed_mem: 257 + amdgpu_bo_free_kernel(&asd_shared_bo, &asd_shared_mc_addr, &asd_shared_buf); 258 + failed: 259 + kfree(cmd); 260 + return ret; 261 + } 262 + 263 + static int psp_load_fw(struct amdgpu_device *adev) 264 + { 265 + int ret; 266 + struct psp_gfx_cmd_resp *cmd; 267 + int i; 268 + struct amdgpu_firmware_info *ucode; 269 + struct psp_context *psp = &adev->psp; 270 + 271 + cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); 272 + if (!cmd) 273 + return -ENOMEM; 274 + 275 + ret = psp_bootloader_load_sysdrv(psp); 276 + if (ret) 277 + goto failed; 278 + 279 + ret = psp_bootloader_load_sos(psp); 280 + if (ret) 281 + goto failed; 282 + 283 + ret = psp_ring_init(psp, PSP_RING_TYPE__KM); 284 + if (ret) 285 + goto failed; 286 + 287 + ret = amdgpu_bo_create_kernel(adev, PSP_FENCE_BUFFER_SIZE, PAGE_SIZE, 288 + AMDGPU_GEM_DOMAIN_VRAM, 289 + &psp->fence_buf_bo, 290 + &psp->fence_buf_mc_addr, 291 + &psp->fence_buf); 292 + if (ret) 293 + goto failed; 294 + 295 + memset(psp->fence_buf, 0, PSP_FENCE_BUFFER_SIZE); 296 + 297 + ret = psp_tmr_init(psp); 298 + if (ret) 299 + goto failed_mem; 300 + 301 + ret = psp_asd_load(psp); 302 + if (ret) 303 + goto failed_mem; 304 + 305 + for (i = 0; i < adev->firmware.max_ucodes; i++) { 306 + ucode = &adev->firmware.ucode[i]; 307 + if (!ucode->fw) 308 + continue; 309 + 310 + if (ucode->ucode_id == AMDGPU_UCODE_ID_SMC && 311 + psp_smu_reload_quirk(psp)) 312 + continue; 313 + 314 + ret = psp_prep_cmd_buf(ucode, cmd); 315 + if (ret) 316 + goto failed_mem; 317 + 318 + ret = psp_cmd_submit_buf(psp, ucode, cmd, 319 + psp->fence_buf_mc_addr, i + 3); 320 + if (ret) 321 + goto failed_mem; 322 + 323 + #if 0 324 + /* check if firmware loaded sucessfully */ 325 + if (!amdgpu_psp_check_fw_loading_status(adev, i)) 326 + return -EINVAL; 327 + #endif 328 + } 329 + 330 + amdgpu_bo_free_kernel(&psp->fence_buf_bo, 331 + &psp->fence_buf_mc_addr, &psp->fence_buf); 332 + kfree(cmd); 333 + 334 + return 0; 335 + 336 + failed_mem: 337 + amdgpu_bo_free_kernel(&psp->fence_buf_bo, 338 + &psp->fence_buf_mc_addr, &psp->fence_buf); 339 + failed: 340 + kfree(cmd); 341 + return ret; 342 + } 343 + 344 + static int psp_hw_init(void *handle) 345 + { 346 + int ret; 347 + struct amdgpu_device *adev = (struct amdgpu_device *)handle; 348 + 349 + 350 + if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) 351 + return 0; 352 + 353 + mutex_lock(&adev->firmware.mutex); 354 + /* 355 + * This sequence is just used on hw_init only once, no need on 356 + * resume. 357 + */ 358 + ret = amdgpu_ucode_init_bo(adev); 359 + if (ret) 360 + goto failed; 361 + 362 + ret = psp_load_fw(adev); 363 + if (ret) { 364 + DRM_ERROR("PSP firmware loading failed\n"); 365 + goto failed; 366 + } 367 + 368 + mutex_unlock(&adev->firmware.mutex); 369 + return 0; 370 + 371 + failed: 372 + adev->firmware.load_type = AMDGPU_FW_LOAD_DIRECT; 373 + mutex_unlock(&adev->firmware.mutex); 374 + return -EINVAL; 375 + } 376 + 377 + static int psp_hw_fini(void *handle) 378 + { 379 + struct amdgpu_device *adev = (struct amdgpu_device *)handle; 380 + struct psp_context *psp = &adev->psp; 381 + 382 + if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) 383 + amdgpu_ucode_fini_bo(adev); 384 + 385 + if (psp->tmr_buf) 386 + amdgpu_bo_free_kernel(&psp->tmr_bo, &psp->tmr_mc_addr, &psp->tmr_buf); 387 + 388 + return 0; 389 + } 390 + 391 + static int psp_suspend(void *handle) 392 + { 393 + return 0; 394 + } 395 + 396 + static int psp_resume(void *handle) 397 + { 398 + int ret; 399 + struct amdgpu_device *adev = (struct amdgpu_device *)handle; 400 + 401 + if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) 402 + return 0; 403 + 404 + mutex_lock(&adev->firmware.mutex); 405 + 406 + ret = psp_load_fw(adev); 407 + if (ret) 408 + DRM_ERROR("PSP resume failed\n"); 409 + 410 + mutex_unlock(&adev->firmware.mutex); 411 + 412 + return ret; 413 + } 414 + 415 + static bool psp_check_fw_loading_status(struct amdgpu_device *adev, 416 + enum AMDGPU_UCODE_ID ucode_type) 417 + { 418 + struct amdgpu_firmware_info *ucode = NULL; 419 + 420 + if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) { 421 + DRM_INFO("firmware is not loaded by PSP\n"); 422 + return true; 423 + } 424 + 425 + if (!adev->firmware.fw_size) 426 + return false; 427 + 428 + ucode = &adev->firmware.ucode[ucode_type]; 429 + if (!ucode->fw || !ucode->ucode_size) 430 + return false; 431 + 432 + return psp_compare_sram_data(&adev->psp, ucode, ucode_type); 433 + } 434 + 435 + static int psp_set_clockgating_state(void *handle, 436 + enum amd_clockgating_state state) 437 + { 438 + return 0; 439 + } 440 + 441 + static int psp_set_powergating_state(void *handle, 442 + enum amd_powergating_state state) 443 + { 444 + return 0; 445 + } 446 + 447 + const struct amd_ip_funcs psp_ip_funcs = { 448 + .name = "psp", 449 + .early_init = psp_early_init, 450 + .late_init = NULL, 451 + .sw_init = psp_sw_init, 452 + .sw_fini = psp_sw_fini, 453 + .hw_init = psp_hw_init, 454 + .hw_fini = psp_hw_fini, 455 + .suspend = psp_suspend, 456 + .resume = psp_resume, 457 + .is_idle = NULL, 458 + .wait_for_idle = NULL, 459 + .soft_reset = NULL, 460 + .set_clockgating_state = psp_set_clockgating_state, 461 + .set_powergating_state = psp_set_powergating_state, 462 + }; 463 + 464 + static const struct amdgpu_psp_funcs psp_funcs = { 465 + .check_fw_loading_status = psp_check_fw_loading_status, 466 + }; 467 + 468 + static void psp_set_funcs(struct amdgpu_device *adev) 469 + { 470 + if (NULL == adev->firmware.funcs) 471 + adev->firmware.funcs = &psp_funcs; 472 + } 473 + 474 + const struct amdgpu_ip_block_version psp_v3_1_ip_block = 475 + { 476 + .type = AMD_IP_BLOCK_TYPE_PSP, 477 + .major = 3, 478 + .minor = 1, 479 + .rev = 0, 480 + .funcs = &psp_ip_funcs, 481 + };
+127
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h
··· 1 + /* 2 + * Copyright 2016 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 + * Author: Huang Rui 23 + * 24 + */ 25 + #ifndef __AMDGPU_PSP_H__ 26 + #define __AMDGPU_PSP_H__ 27 + 28 + #include "amdgpu.h" 29 + #include "psp_gfx_if.h" 30 + 31 + #define PSP_FENCE_BUFFER_SIZE 0x1000 32 + #define PSP_CMD_BUFFER_SIZE 0x1000 33 + #define PSP_ASD_BIN_SIZE 0x40000 34 + #define PSP_ASD_SHARED_MEM_SIZE 0x4000 35 + 36 + enum psp_ring_type 37 + { 38 + PSP_RING_TYPE__INVALID = 0, 39 + /* 40 + * These values map to the way the PSP kernel identifies the 41 + * rings. 42 + */ 43 + PSP_RING_TYPE__UM = 1, /* User mode ring (formerly called RBI) */ 44 + PSP_RING_TYPE__KM = 2 /* Kernel mode ring (formerly called GPCOM) */ 45 + }; 46 + 47 + struct psp_ring 48 + { 49 + enum psp_ring_type ring_type; 50 + struct psp_gfx_rb_frame *ring_mem; 51 + uint64_t ring_mem_mc_addr; 52 + void *ring_mem_handle; 53 + uint32_t ring_size; 54 + }; 55 + 56 + struct psp_context 57 + { 58 + struct amdgpu_device *adev; 59 + struct psp_ring km_ring; 60 + 61 + int (*init_microcode)(struct psp_context *psp); 62 + int (*bootloader_load_sysdrv)(struct psp_context *psp); 63 + int (*bootloader_load_sos)(struct psp_context *psp); 64 + int (*prep_cmd_buf)(struct amdgpu_firmware_info *ucode, 65 + struct psp_gfx_cmd_resp *cmd); 66 + int (*ring_init)(struct psp_context *psp, enum psp_ring_type ring_type); 67 + int (*cmd_submit)(struct psp_context *psp, struct amdgpu_firmware_info *ucode, 68 + uint64_t cmd_buf_mc_addr, uint64_t fence_mc_addr, int index); 69 + bool (*compare_sram_data)(struct psp_context *psp, 70 + struct amdgpu_firmware_info *ucode, 71 + enum AMDGPU_UCODE_ID ucode_type); 72 + bool (*smu_reload_quirk)(struct psp_context *psp); 73 + 74 + /* sos firmware */ 75 + const struct firmware *sos_fw; 76 + uint32_t sos_fw_version; 77 + uint32_t sos_feature_version; 78 + uint32_t sys_bin_size; 79 + uint32_t sos_bin_size; 80 + uint8_t *sys_start_addr; 81 + uint8_t *sos_start_addr; 82 + 83 + /* tmr buffer */ 84 + struct amdgpu_bo *tmr_bo; 85 + uint64_t tmr_mc_addr; 86 + void *tmr_buf; 87 + 88 + /* asd firmware */ 89 + const struct firmware *asd_fw; 90 + uint32_t asd_fw_version; 91 + uint32_t asd_feature_version; 92 + uint32_t asd_ucode_size; 93 + uint8_t *asd_start_addr; 94 + 95 + /* fence buffer */ 96 + struct amdgpu_bo *fence_buf_bo; 97 + uint64_t fence_buf_mc_addr; 98 + void *fence_buf; 99 + }; 100 + 101 + struct amdgpu_psp_funcs { 102 + bool (*check_fw_loading_status)(struct amdgpu_device *adev, 103 + enum AMDGPU_UCODE_ID); 104 + }; 105 + 106 + #define psp_prep_cmd_buf(ucode, type) (psp)->prep_cmd_buf((ucode), (type)) 107 + #define psp_ring_init(psp, type) (psp)->ring_init((psp), (type)) 108 + #define psp_cmd_submit(psp, ucode, cmd_mc, fence_mc, index) \ 109 + (psp)->cmd_submit((psp), (ucode), (cmd_mc), (fence_mc), (index)) 110 + #define psp_compare_sram_data(psp, ucode, type) \ 111 + (psp)->compare_sram_data((psp), (ucode), (type)) 112 + #define psp_init_microcode(psp) \ 113 + ((psp)->init_microcode ? (psp)->init_microcode((psp)) : 0) 114 + #define psp_bootloader_load_sysdrv(psp) \ 115 + ((psp)->bootloader_load_sysdrv ? (psp)->bootloader_load_sysdrv((psp)) : 0) 116 + #define psp_bootloader_load_sos(psp) \ 117 + ((psp)->bootloader_load_sos ? (psp)->bootloader_load_sos((psp)) : 0) 118 + #define psp_smu_reload_quirk(psp) \ 119 + ((psp)->smu_reload_quirk ? (psp)->smu_reload_quirk((psp)) : false) 120 + 121 + extern const struct amd_ip_funcs psp_ip_funcs; 122 + 123 + extern const struct amdgpu_ip_block_version psp_v3_1_ip_block; 124 + extern int psp_wait_for(struct psp_context *psp, uint32_t reg_index, 125 + uint32_t field_val, uint32_t mask, bool check_changed); 126 + 127 + #endif
+269
drivers/gpu/drm/amd/amdgpu/psp_gfx_if.h
··· 1 + /* 2 + * Copyright 2017 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 + */ 23 + 24 + #ifndef _PSP_TEE_GFX_IF_H_ 25 + #define _PSP_TEE_GFX_IF_H_ 26 + 27 + #define PSP_GFX_CMD_BUF_VERSION 0x00000001 28 + 29 + #define GFX_CMD_STATUS_MASK 0x0000FFFF 30 + #define GFX_CMD_ID_MASK 0x000F0000 31 + #define GFX_CMD_RESERVED_MASK 0x7FF00000 32 + #define GFX_CMD_RESPONSE_MASK 0x80000000 33 + 34 + /* TEE Gfx Command IDs for the register interface. 35 + * Command ID must be between 0x00010000 and 0x000F0000. 36 + */ 37 + enum psp_gfx_crtl_cmd_id 38 + { 39 + GFX_CTRL_CMD_ID_INIT_RBI_RING = 0x00010000, /* initialize RBI ring */ 40 + GFX_CTRL_CMD_ID_INIT_GPCOM_RING = 0x00020000, /* initialize GPCOM ring */ 41 + GFX_CTRL_CMD_ID_DESTROY_RINGS = 0x00030000, /* destroy rings */ 42 + GFX_CTRL_CMD_ID_CAN_INIT_RINGS = 0x00040000, /* is it allowed to initialized the rings */ 43 + 44 + GFX_CTRL_CMD_ID_MAX = 0x000F0000, /* max command ID */ 45 + }; 46 + 47 + 48 + /* Control registers of the TEE Gfx interface. These are located in 49 + * SRBM-to-PSP mailbox registers (total 8 registers). 50 + */ 51 + struct psp_gfx_ctrl 52 + { 53 + volatile uint32_t cmd_resp; /* +0 Command/Response register for Gfx commands */ 54 + volatile uint32_t rbi_wptr; /* +4 Write pointer (index) of RBI ring */ 55 + volatile uint32_t rbi_rptr; /* +8 Read pointer (index) of RBI ring */ 56 + volatile uint32_t gpcom_wptr; /* +12 Write pointer (index) of GPCOM ring */ 57 + volatile uint32_t gpcom_rptr; /* +16 Read pointer (index) of GPCOM ring */ 58 + volatile uint32_t ring_addr_lo; /* +20 bits [31:0] of physical address of ring buffer */ 59 + volatile uint32_t ring_addr_hi; /* +24 bits [63:32] of physical address of ring buffer */ 60 + volatile uint32_t ring_buf_size; /* +28 Ring buffer size (in bytes) */ 61 + 62 + }; 63 + 64 + 65 + /* Response flag is set in the command when command is completed by PSP. 66 + * Used in the GFX_CTRL.CmdResp. 67 + * When PSP GFX I/F is initialized, the flag is set. 68 + */ 69 + #define GFX_FLAG_RESPONSE 0x80000000 70 + 71 + 72 + /* TEE Gfx Command IDs for the ring buffer interface. */ 73 + enum psp_gfx_cmd_id 74 + { 75 + GFX_CMD_ID_LOAD_TA = 0x00000001, /* load TA */ 76 + GFX_CMD_ID_UNLOAD_TA = 0x00000002, /* unload TA */ 77 + GFX_CMD_ID_INVOKE_CMD = 0x00000003, /* send command to TA */ 78 + GFX_CMD_ID_LOAD_ASD = 0x00000004, /* load ASD Driver */ 79 + GFX_CMD_ID_SETUP_TMR = 0x00000005, /* setup TMR region */ 80 + GFX_CMD_ID_LOAD_IP_FW = 0x00000006, /* load HW IP FW */ 81 + 82 + }; 83 + 84 + 85 + /* Command to load Trusted Application binary into PSP OS. */ 86 + struct psp_gfx_cmd_load_ta 87 + { 88 + uint32_t app_phy_addr_lo; /* bits [31:0] of the physical address of the TA binary (must be 4 KB aligned) */ 89 + uint32_t app_phy_addr_hi; /* bits [63:32] of the physical address of the TA binary */ 90 + uint32_t app_len; /* length of the TA binary in bytes */ 91 + uint32_t cmd_buf_phy_addr_lo; /* bits [31:0] of the physical address of CMD buffer (must be 4 KB aligned) */ 92 + uint32_t cmd_buf_phy_addr_hi; /* bits [63:32] of the physical address of CMD buffer */ 93 + uint32_t cmd_buf_len; /* length of the CMD buffer in bytes; must be multiple of 4 KB */ 94 + 95 + /* Note: CmdBufLen can be set to 0. In this case no persistent CMD buffer is provided 96 + * for the TA. Each InvokeCommand can have dinamically mapped CMD buffer instead 97 + * of using global persistent buffer. 98 + */ 99 + }; 100 + 101 + 102 + /* Command to Unload Trusted Application binary from PSP OS. */ 103 + struct psp_gfx_cmd_unload_ta 104 + { 105 + uint32_t session_id; /* Session ID of the loaded TA to be unloaded */ 106 + 107 + }; 108 + 109 + 110 + /* Shared buffers for InvokeCommand. 111 + */ 112 + struct psp_gfx_buf_desc 113 + { 114 + uint32_t buf_phy_addr_lo; /* bits [31:0] of physical address of the buffer (must be 4 KB aligned) */ 115 + uint32_t buf_phy_addr_hi; /* bits [63:32] of physical address of the buffer */ 116 + uint32_t buf_size; /* buffer size in bytes (must be multiple of 4 KB and no bigger than 64 MB) */ 117 + 118 + }; 119 + 120 + /* Max number of descriptors for one shared buffer (in how many different 121 + * physical locations one shared buffer can be stored). If buffer is too much 122 + * fragmented, error will be returned. 123 + */ 124 + #define GFX_BUF_MAX_DESC 64 125 + 126 + struct psp_gfx_buf_list 127 + { 128 + uint32_t num_desc; /* number of buffer descriptors in the list */ 129 + uint32_t total_size; /* total size of all buffers in the list in bytes (must be multiple of 4 KB) */ 130 + struct psp_gfx_buf_desc buf_desc[GFX_BUF_MAX_DESC]; /* list of buffer descriptors */ 131 + 132 + /* total 776 bytes */ 133 + }; 134 + 135 + /* Command to execute InvokeCommand entry point of the TA. */ 136 + struct psp_gfx_cmd_invoke_cmd 137 + { 138 + uint32_t session_id; /* Session ID of the TA to be executed */ 139 + uint32_t ta_cmd_id; /* Command ID to be sent to TA */ 140 + struct psp_gfx_buf_list buf; /* one indirect buffer (scatter/gather list) */ 141 + 142 + }; 143 + 144 + 145 + /* Command to setup TMR region. */ 146 + struct psp_gfx_cmd_setup_tmr 147 + { 148 + uint32_t buf_phy_addr_lo; /* bits [31:0] of physical address of TMR buffer (must be 4 KB aligned) */ 149 + uint32_t buf_phy_addr_hi; /* bits [63:32] of physical address of TMR buffer */ 150 + uint32_t buf_size; /* buffer size in bytes (must be multiple of 4 KB) */ 151 + 152 + }; 153 + 154 + 155 + /* FW types for GFX_CMD_ID_LOAD_IP_FW command. Limit 31. */ 156 + enum psp_gfx_fw_type 157 + { 158 + GFX_FW_TYPE_NONE = 0, 159 + GFX_FW_TYPE_CP_ME = 1, 160 + GFX_FW_TYPE_CP_PFP = 2, 161 + GFX_FW_TYPE_CP_CE = 3, 162 + GFX_FW_TYPE_CP_MEC = 4, 163 + GFX_FW_TYPE_CP_MEC_ME1 = 5, 164 + GFX_FW_TYPE_CP_MEC_ME2 = 6, 165 + GFX_FW_TYPE_RLC_V = 7, 166 + GFX_FW_TYPE_RLC_G = 8, 167 + GFX_FW_TYPE_SDMA0 = 9, 168 + GFX_FW_TYPE_SDMA1 = 10, 169 + GFX_FW_TYPE_DMCU_ERAM = 11, 170 + GFX_FW_TYPE_DMCU_ISR = 12, 171 + GFX_FW_TYPE_VCN = 13, 172 + GFX_FW_TYPE_UVD = 14, 173 + GFX_FW_TYPE_VCE = 15, 174 + GFX_FW_TYPE_ISP = 16, 175 + GFX_FW_TYPE_ACP = 17, 176 + GFX_FW_TYPE_SMU = 18, 177 + }; 178 + 179 + /* Command to load HW IP FW. */ 180 + struct psp_gfx_cmd_load_ip_fw 181 + { 182 + uint32_t fw_phy_addr_lo; /* bits [31:0] of physical address of FW location (must be 4 KB aligned) */ 183 + uint32_t fw_phy_addr_hi; /* bits [63:32] of physical address of FW location */ 184 + uint32_t fw_size; /* FW buffer size in bytes */ 185 + enum psp_gfx_fw_type fw_type; /* FW type */ 186 + 187 + }; 188 + 189 + 190 + /* All GFX ring buffer commands. */ 191 + union psp_gfx_commands 192 + { 193 + struct psp_gfx_cmd_load_ta cmd_load_ta; 194 + struct psp_gfx_cmd_unload_ta cmd_unload_ta; 195 + struct psp_gfx_cmd_invoke_cmd cmd_invoke_cmd; 196 + struct psp_gfx_cmd_setup_tmr cmd_setup_tmr; 197 + struct psp_gfx_cmd_load_ip_fw cmd_load_ip_fw; 198 + 199 + }; 200 + 201 + 202 + /* Structure of GFX Response buffer. 203 + * For GPCOM I/F it is part of GFX_CMD_RESP buffer, for RBI 204 + * it is separate buffer. 205 + */ 206 + struct psp_gfx_resp 207 + { 208 + uint32_t status; /* +0 status of command execution */ 209 + uint32_t session_id; /* +4 session ID in response to LoadTa command */ 210 + uint32_t fw_addr_lo; /* +8 bits [31:0] of FW address within TMR (in response to cmd_load_ip_fw command) */ 211 + uint32_t fw_addr_hi; /* +12 bits [63:32] of FW address within TMR (in response to cmd_load_ip_fw command) */ 212 + 213 + uint32_t reserved[4]; 214 + 215 + /* total 32 bytes */ 216 + }; 217 + 218 + /* Structure of Command buffer pointed by psp_gfx_rb_frame.cmd_buf_addr_hi 219 + * and psp_gfx_rb_frame.cmd_buf_addr_lo. 220 + */ 221 + struct psp_gfx_cmd_resp 222 + { 223 + uint32_t buf_size; /* +0 total size of the buffer in bytes */ 224 + uint32_t buf_version; /* +4 version of the buffer strusture; must be PSP_GFX_CMD_BUF_VERSION */ 225 + uint32_t cmd_id; /* +8 command ID */ 226 + 227 + /* These fields are used for RBI only. They are all 0 in GPCOM commands 228 + */ 229 + uint32_t resp_buf_addr_lo; /* +12 bits [31:0] of physical address of response buffer (must be 4 KB aligned) */ 230 + uint32_t resp_buf_addr_hi; /* +16 bits [63:32] of physical address of response buffer */ 231 + uint32_t resp_offset; /* +20 offset within response buffer */ 232 + uint32_t resp_buf_size; /* +24 total size of the response buffer in bytes */ 233 + 234 + union psp_gfx_commands cmd; /* +28 command specific structures */ 235 + 236 + uint8_t reserved_1[864 - sizeof(union psp_gfx_commands) - 28]; 237 + 238 + /* Note: Resp is part of this buffer for GPCOM ring. For RBI ring the response 239 + * is separate buffer pointed by resp_buf_addr_hi and resp_buf_addr_lo. 240 + */ 241 + struct psp_gfx_resp resp; /* +864 response */ 242 + 243 + uint8_t reserved_2[1024 - 864 - sizeof(struct psp_gfx_resp)]; 244 + 245 + /* total size 1024 bytes */ 246 + }; 247 + 248 + 249 + #define FRAME_TYPE_DESTROY 1 /* frame sent by KMD driver when UMD Scheduler context is destroyed*/ 250 + 251 + /* Structure of the Ring Buffer Frame */ 252 + struct psp_gfx_rb_frame 253 + { 254 + uint32_t cmd_buf_addr_lo; /* +0 bits [31:0] of physical address of command buffer (must be 4 KB aligned) */ 255 + uint32_t cmd_buf_addr_hi; /* +4 bits [63:32] of physical address of command buffer */ 256 + uint32_t cmd_buf_size; /* +8 command buffer size in bytes */ 257 + uint32_t fence_addr_lo; /* +12 bits [31:0] of physical address of Fence for this frame */ 258 + uint32_t fence_addr_hi; /* +16 bits [63:32] of physical address of Fence for this frame */ 259 + uint32_t fence_value; /* +20 Fence value */ 260 + uint32_t sid_lo; /* +24 bits [31:0] of SID value (used only for RBI frames) */ 261 + uint32_t sid_hi; /* +28 bits [63:32] of SID value (used only for RBI frames) */ 262 + uint8_t vmid; /* +32 VMID value used for mapping of all addresses for this frame */ 263 + uint8_t frame_type; /* +33 1: destory context frame, 0: all other frames; used only for RBI frames */ 264 + uint8_t reserved1[2]; /* +34 reserved, must be 0 */ 265 + uint32_t reserved2[7]; /* +40 reserved, must be 0 */ 266 + /* total 64 bytes */ 267 + }; 268 + 269 + #endif /* _PSP_TEE_GFX_IF_H_ */
+507
drivers/gpu/drm/amd/amdgpu/psp_v3_1.c
··· 1 + /* 2 + * Copyright 2016 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 + * Author: Huang Rui 23 + * 24 + */ 25 + 26 + #include <linux/firmware.h> 27 + #include "drmP.h" 28 + #include "amdgpu.h" 29 + #include "amdgpu_psp.h" 30 + #include "amdgpu_ucode.h" 31 + #include "soc15_common.h" 32 + #include "psp_v3_1.h" 33 + 34 + #include "vega10/soc15ip.h" 35 + #include "vega10/MP/mp_9_0_offset.h" 36 + #include "vega10/MP/mp_9_0_sh_mask.h" 37 + #include "vega10/GC/gc_9_0_offset.h" 38 + #include "vega10/SDMA0/sdma0_4_0_offset.h" 39 + #include "vega10/NBIO/nbio_6_1_offset.h" 40 + 41 + MODULE_FIRMWARE("amdgpu/vega10_sos.bin"); 42 + MODULE_FIRMWARE("amdgpu/vega10_asd.bin"); 43 + 44 + #define smnMP1_FIRMWARE_FLAGS 0x3010028 45 + 46 + static int 47 + psp_v3_1_get_fw_type(struct amdgpu_firmware_info *ucode, enum psp_gfx_fw_type *type) 48 + { 49 + switch(ucode->ucode_id) { 50 + case AMDGPU_UCODE_ID_SDMA0: 51 + *type = GFX_FW_TYPE_SDMA0; 52 + break; 53 + case AMDGPU_UCODE_ID_SDMA1: 54 + *type = GFX_FW_TYPE_SDMA1; 55 + break; 56 + case AMDGPU_UCODE_ID_CP_CE: 57 + *type = GFX_FW_TYPE_CP_CE; 58 + break; 59 + case AMDGPU_UCODE_ID_CP_PFP: 60 + *type = GFX_FW_TYPE_CP_PFP; 61 + break; 62 + case AMDGPU_UCODE_ID_CP_ME: 63 + *type = GFX_FW_TYPE_CP_ME; 64 + break; 65 + case AMDGPU_UCODE_ID_CP_MEC1: 66 + *type = GFX_FW_TYPE_CP_MEC; 67 + break; 68 + case AMDGPU_UCODE_ID_CP_MEC1_JT: 69 + *type = GFX_FW_TYPE_CP_MEC_ME1; 70 + break; 71 + case AMDGPU_UCODE_ID_CP_MEC2: 72 + *type = GFX_FW_TYPE_CP_MEC; 73 + break; 74 + case AMDGPU_UCODE_ID_CP_MEC2_JT: 75 + *type = GFX_FW_TYPE_CP_MEC_ME2; 76 + break; 77 + case AMDGPU_UCODE_ID_RLC_G: 78 + *type = GFX_FW_TYPE_RLC_G; 79 + break; 80 + case AMDGPU_UCODE_ID_SMC: 81 + *type = GFX_FW_TYPE_SMU; 82 + break; 83 + case AMDGPU_UCODE_ID_UVD: 84 + *type = GFX_FW_TYPE_UVD; 85 + break; 86 + case AMDGPU_UCODE_ID_VCE: 87 + *type = GFX_FW_TYPE_VCE; 88 + break; 89 + case AMDGPU_UCODE_ID_MAXIMUM: 90 + default: 91 + return -EINVAL; 92 + } 93 + 94 + return 0; 95 + } 96 + 97 + int psp_v3_1_init_microcode(struct psp_context *psp) 98 + { 99 + struct amdgpu_device *adev = psp->adev; 100 + const char *chip_name; 101 + char fw_name[30]; 102 + int err = 0; 103 + const struct psp_firmware_header_v1_0 *hdr; 104 + 105 + DRM_DEBUG("\n"); 106 + 107 + switch (adev->asic_type) { 108 + case CHIP_VEGA10: 109 + chip_name = "vega10"; 110 + break; 111 + default: BUG(); 112 + } 113 + 114 + snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_sos.bin", chip_name); 115 + err = request_firmware(&adev->psp.sos_fw, fw_name, adev->dev); 116 + if (err) 117 + goto out; 118 + 119 + err = amdgpu_ucode_validate(adev->psp.sos_fw); 120 + if (err) 121 + goto out; 122 + 123 + hdr = (const struct psp_firmware_header_v1_0 *)adev->psp.sos_fw->data; 124 + adev->psp.sos_fw_version = le32_to_cpu(hdr->header.ucode_version); 125 + adev->psp.sos_feature_version = le32_to_cpu(hdr->ucode_feature_version); 126 + adev->psp.sos_bin_size = le32_to_cpu(hdr->sos_size_bytes); 127 + adev->psp.sys_bin_size = le32_to_cpu(hdr->header.ucode_size_bytes) - 128 + le32_to_cpu(hdr->sos_size_bytes); 129 + adev->psp.sys_start_addr = (uint8_t *)hdr + 130 + le32_to_cpu(hdr->header.ucode_array_offset_bytes); 131 + adev->psp.sos_start_addr = (uint8_t *)adev->psp.sys_start_addr + 132 + le32_to_cpu(hdr->sos_offset_bytes); 133 + 134 + snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_asd.bin", chip_name); 135 + err = request_firmware(&adev->psp.asd_fw, fw_name, adev->dev); 136 + if (err) 137 + goto out; 138 + 139 + err = amdgpu_ucode_validate(adev->psp.asd_fw); 140 + if (err) 141 + goto out; 142 + 143 + hdr = (const struct psp_firmware_header_v1_0 *)adev->psp.asd_fw->data; 144 + adev->psp.asd_fw_version = le32_to_cpu(hdr->header.ucode_version); 145 + adev->psp.asd_feature_version = le32_to_cpu(hdr->ucode_feature_version); 146 + adev->psp.asd_ucode_size = le32_to_cpu(hdr->header.ucode_size_bytes); 147 + adev->psp.asd_start_addr = (uint8_t *)hdr + 148 + le32_to_cpu(hdr->header.ucode_array_offset_bytes); 149 + 150 + return 0; 151 + out: 152 + if (err) { 153 + dev_err(adev->dev, 154 + "psp v3.1: Failed to load firmware \"%s\"\n", 155 + fw_name); 156 + release_firmware(adev->psp.sos_fw); 157 + adev->psp.sos_fw = NULL; 158 + release_firmware(adev->psp.asd_fw); 159 + adev->psp.asd_fw = NULL; 160 + } 161 + 162 + return err; 163 + } 164 + 165 + int psp_v3_1_bootloader_load_sysdrv(struct psp_context *psp) 166 + { 167 + int ret; 168 + uint32_t psp_gfxdrv_command_reg = 0; 169 + struct amdgpu_bo *psp_sysdrv; 170 + void *psp_sysdrv_virt = NULL; 171 + uint64_t psp_sysdrv_mem; 172 + struct amdgpu_device *adev = psp->adev; 173 + uint32_t size; 174 + 175 + /* Wait for bootloader to signify that is ready having bit 31 of C2PMSG_35 set to 1 */ 176 + ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_35), 177 + 0x80000000, 0x80000000, false); 178 + if (ret) 179 + return ret; 180 + 181 + /* 182 + * Create a 1 meg GART memory to store the psp sys driver 183 + * binary with a 1 meg aligned address 184 + */ 185 + size = (psp->sys_bin_size + (PSP_BOOTLOADER_1_MEG_ALIGNMENT - 1)) & 186 + (~(PSP_BOOTLOADER_1_MEG_ALIGNMENT - 1)); 187 + 188 + ret = amdgpu_bo_create_kernel(adev, size, PSP_BOOTLOADER_1_MEG_ALIGNMENT, 189 + AMDGPU_GEM_DOMAIN_GTT, 190 + &psp_sysdrv, 191 + &psp_sysdrv_mem, 192 + &psp_sysdrv_virt); 193 + if (ret) 194 + return ret; 195 + 196 + /* Copy PSP System Driver binary to memory */ 197 + memcpy(psp_sysdrv_virt, psp->sys_start_addr, psp->sys_bin_size); 198 + 199 + /* Provide the sys driver to bootrom */ 200 + WREG32(SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_36), 201 + (uint32_t)(psp_sysdrv_mem >> 20)); 202 + psp_gfxdrv_command_reg = 1 << 16; 203 + WREG32(SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_35), 204 + psp_gfxdrv_command_reg); 205 + 206 + /* there might be handshake issue with hardware which needs delay */ 207 + mdelay(20); 208 + 209 + ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_35), 210 + 0x80000000, 0x80000000, false); 211 + 212 + amdgpu_bo_free_kernel(&psp_sysdrv, &psp_sysdrv_mem, &psp_sysdrv_virt); 213 + 214 + return ret; 215 + } 216 + 217 + int psp_v3_1_bootloader_load_sos(struct psp_context *psp) 218 + { 219 + int ret; 220 + unsigned int psp_gfxdrv_command_reg = 0; 221 + struct amdgpu_bo *psp_sos; 222 + void *psp_sos_virt = NULL; 223 + uint64_t psp_sos_mem; 224 + struct amdgpu_device *adev = psp->adev; 225 + uint32_t size; 226 + 227 + /* Wait for bootloader to signify that is ready having bit 31 of C2PMSG_35 set to 1 */ 228 + ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_35), 229 + 0x80000000, 0x80000000, false); 230 + if (ret) 231 + return ret; 232 + 233 + size = (psp->sos_bin_size + (PSP_BOOTLOADER_1_MEG_ALIGNMENT - 1)) & 234 + (~((uint64_t)PSP_BOOTLOADER_1_MEG_ALIGNMENT - 1)); 235 + 236 + ret = amdgpu_bo_create_kernel(adev, size, PSP_BOOTLOADER_1_MEG_ALIGNMENT, 237 + AMDGPU_GEM_DOMAIN_GTT, 238 + &psp_sos, 239 + &psp_sos_mem, 240 + &psp_sos_virt); 241 + if (ret) 242 + return ret; 243 + 244 + /* Copy Secure OS binary to PSP memory */ 245 + memcpy(psp_sos_virt, psp->sos_start_addr, psp->sos_bin_size); 246 + 247 + /* Provide the PSP secure OS to bootrom */ 248 + WREG32(SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_36), 249 + (uint32_t)(psp_sos_mem >> 20)); 250 + psp_gfxdrv_command_reg = 2 << 16; 251 + WREG32(SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_35), 252 + psp_gfxdrv_command_reg); 253 + 254 + /* there might be handshake issue with hardware which needs delay */ 255 + mdelay(20); 256 + #if 0 257 + ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_81), 258 + RREG32(SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_81)), 259 + 0, true); 260 + #endif 261 + 262 + amdgpu_bo_free_kernel(&psp_sos, &psp_sos_mem, &psp_sos_virt); 263 + 264 + return ret; 265 + } 266 + 267 + int psp_v3_1_prep_cmd_buf(struct amdgpu_firmware_info *ucode, struct psp_gfx_cmd_resp *cmd) 268 + { 269 + int ret; 270 + uint64_t fw_mem_mc_addr = ucode->mc_addr; 271 + 272 + memset(cmd, 0, sizeof(struct psp_gfx_cmd_resp)); 273 + 274 + cmd->cmd_id = GFX_CMD_ID_LOAD_IP_FW; 275 + cmd->cmd.cmd_load_ip_fw.fw_phy_addr_lo = (uint32_t)fw_mem_mc_addr; 276 + cmd->cmd.cmd_load_ip_fw.fw_phy_addr_hi = (uint32_t)((uint64_t)fw_mem_mc_addr >> 32); 277 + cmd->cmd.cmd_load_ip_fw.fw_size = ucode->ucode_size; 278 + 279 + ret = psp_v3_1_get_fw_type(ucode, &cmd->cmd.cmd_load_ip_fw.fw_type); 280 + if (ret) 281 + DRM_ERROR("Unknown firmware type\n"); 282 + 283 + return ret; 284 + } 285 + 286 + int psp_v3_1_ring_init(struct psp_context *psp, enum psp_ring_type ring_type) 287 + { 288 + int ret = 0; 289 + unsigned int psp_ring_reg = 0; 290 + struct psp_ring *ring; 291 + struct amdgpu_device *adev = psp->adev; 292 + 293 + ring = &psp->km_ring; 294 + 295 + ring->ring_type = ring_type; 296 + 297 + /* allocate 4k Page of Local Frame Buffer memory for ring */ 298 + ring->ring_size = 0x1000; 299 + ret = amdgpu_bo_create_kernel(adev, ring->ring_size, PAGE_SIZE, 300 + AMDGPU_GEM_DOMAIN_VRAM, 301 + &adev->firmware.rbuf, 302 + &ring->ring_mem_mc_addr, 303 + (void **)&ring->ring_mem); 304 + if (ret) { 305 + ring->ring_size = 0; 306 + return ret; 307 + } 308 + 309 + /* Write low address of the ring to C2PMSG_69 */ 310 + psp_ring_reg = lower_32_bits(ring->ring_mem_mc_addr); 311 + WREG32(SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_69), psp_ring_reg); 312 + /* Write high address of the ring to C2PMSG_70 */ 313 + psp_ring_reg = upper_32_bits(ring->ring_mem_mc_addr); 314 + WREG32(SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_70), psp_ring_reg); 315 + /* Write size of ring to C2PMSG_71 */ 316 + psp_ring_reg = ring->ring_size; 317 + WREG32(SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_71), psp_ring_reg); 318 + /* Write the ring initialization command to C2PMSG_64 */ 319 + psp_ring_reg = ring_type; 320 + psp_ring_reg = psp_ring_reg << 16; 321 + WREG32(SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64), psp_ring_reg); 322 + 323 + /* there might be handshake issue with hardware which needs delay */ 324 + mdelay(20); 325 + 326 + /* Wait for response flag (bit 31) in C2PMSG_64 */ 327 + ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64), 328 + 0x80000000, 0x8000FFFF, false); 329 + 330 + return ret; 331 + } 332 + 333 + int psp_v3_1_cmd_submit(struct psp_context *psp, 334 + struct amdgpu_firmware_info *ucode, 335 + uint64_t cmd_buf_mc_addr, uint64_t fence_mc_addr, 336 + int index) 337 + { 338 + unsigned int psp_write_ptr_reg = 0; 339 + struct psp_gfx_rb_frame * write_frame = psp->km_ring.ring_mem; 340 + struct psp_ring *ring = &psp->km_ring; 341 + struct amdgpu_device *adev = psp->adev; 342 + uint32_t ring_size_dw = ring->ring_size / 4; 343 + uint32_t rb_frame_size_dw = sizeof(struct psp_gfx_rb_frame) / 4; 344 + 345 + /* KM (GPCOM) prepare write pointer */ 346 + psp_write_ptr_reg = RREG32(SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_67)); 347 + 348 + /* Update KM RB frame pointer to new frame */ 349 + /* write_frame ptr increments by size of rb_frame in bytes */ 350 + /* psp_write_ptr_reg increments by size of rb_frame in DWORDs */ 351 + if ((psp_write_ptr_reg % ring_size_dw) == 0) 352 + write_frame = ring->ring_mem; 353 + else 354 + write_frame = ring->ring_mem + (psp_write_ptr_reg / rb_frame_size_dw); 355 + 356 + /* Initialize KM RB frame */ 357 + memset(write_frame, 0, sizeof(struct psp_gfx_rb_frame)); 358 + 359 + /* Update KM RB frame */ 360 + write_frame->cmd_buf_addr_hi = (unsigned int)(cmd_buf_mc_addr >> 32); 361 + write_frame->cmd_buf_addr_lo = (unsigned int)(cmd_buf_mc_addr); 362 + write_frame->fence_addr_hi = (unsigned int)(fence_mc_addr >> 32); 363 + write_frame->fence_addr_lo = (unsigned int)(fence_mc_addr); 364 + write_frame->fence_value = index; 365 + 366 + /* Update the write Pointer in DWORDs */ 367 + psp_write_ptr_reg = (psp_write_ptr_reg + rb_frame_size_dw) % ring_size_dw; 368 + WREG32(SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_67), psp_write_ptr_reg); 369 + 370 + return 0; 371 + } 372 + 373 + static int 374 + psp_v3_1_sram_map(unsigned int *sram_offset, unsigned int *sram_addr_reg_offset, 375 + unsigned int *sram_data_reg_offset, 376 + enum AMDGPU_UCODE_ID ucode_id) 377 + { 378 + int ret = 0; 379 + 380 + switch(ucode_id) { 381 + /* TODO: needs to confirm */ 382 + #if 0 383 + case AMDGPU_UCODE_ID_SMC: 384 + *sram_offset = 0; 385 + *sram_addr_reg_offset = 0; 386 + *sram_data_reg_offset = 0; 387 + break; 388 + #endif 389 + 390 + case AMDGPU_UCODE_ID_CP_CE: 391 + *sram_offset = 0x0; 392 + *sram_addr_reg_offset = SOC15_REG_OFFSET(GC, 0, mmCP_CE_UCODE_ADDR); 393 + *sram_data_reg_offset = SOC15_REG_OFFSET(GC, 0, mmCP_CE_UCODE_DATA); 394 + break; 395 + 396 + case AMDGPU_UCODE_ID_CP_PFP: 397 + *sram_offset = 0x0; 398 + *sram_addr_reg_offset = SOC15_REG_OFFSET(GC, 0, mmCP_PFP_UCODE_ADDR); 399 + *sram_data_reg_offset = SOC15_REG_OFFSET(GC, 0, mmCP_PFP_UCODE_DATA); 400 + break; 401 + 402 + case AMDGPU_UCODE_ID_CP_ME: 403 + *sram_offset = 0x0; 404 + *sram_addr_reg_offset = SOC15_REG_OFFSET(GC, 0, mmCP_HYP_ME_UCODE_ADDR); 405 + *sram_data_reg_offset = SOC15_REG_OFFSET(GC, 0, mmCP_HYP_ME_UCODE_DATA); 406 + break; 407 + 408 + case AMDGPU_UCODE_ID_CP_MEC1: 409 + *sram_offset = 0x10000; 410 + *sram_addr_reg_offset = SOC15_REG_OFFSET(GC, 0, mmCP_MEC_ME1_UCODE_ADDR); 411 + *sram_data_reg_offset = SOC15_REG_OFFSET(GC, 0, mmCP_MEC_ME1_UCODE_DATA); 412 + break; 413 + 414 + case AMDGPU_UCODE_ID_CP_MEC2: 415 + *sram_offset = 0x10000; 416 + *sram_addr_reg_offset = SOC15_REG_OFFSET(GC, 0, mmCP_HYP_MEC2_UCODE_ADDR); 417 + *sram_data_reg_offset = SOC15_REG_OFFSET(GC, 0, mmCP_HYP_MEC2_UCODE_DATA); 418 + break; 419 + 420 + case AMDGPU_UCODE_ID_RLC_G: 421 + *sram_offset = 0x2000; 422 + *sram_addr_reg_offset = SOC15_REG_OFFSET(GC, 0, mmRLC_GPM_UCODE_ADDR); 423 + *sram_data_reg_offset = SOC15_REG_OFFSET(GC, 0, mmRLC_GPM_UCODE_DATA); 424 + break; 425 + 426 + case AMDGPU_UCODE_ID_SDMA0: 427 + *sram_offset = 0x0; 428 + *sram_addr_reg_offset = SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_UCODE_ADDR); 429 + *sram_data_reg_offset = SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_UCODE_DATA); 430 + break; 431 + 432 + /* TODO: needs to confirm */ 433 + #if 0 434 + case AMDGPU_UCODE_ID_SDMA1: 435 + *sram_offset = ; 436 + *sram_addr_reg_offset = ; 437 + break; 438 + 439 + case AMDGPU_UCODE_ID_UVD: 440 + *sram_offset = ; 441 + *sram_addr_reg_offset = ; 442 + break; 443 + 444 + case AMDGPU_UCODE_ID_VCE: 445 + *sram_offset = ; 446 + *sram_addr_reg_offset = ; 447 + break; 448 + #endif 449 + 450 + case AMDGPU_UCODE_ID_MAXIMUM: 451 + default: 452 + ret = -EINVAL; 453 + break; 454 + } 455 + 456 + return ret; 457 + } 458 + 459 + bool psp_v3_1_compare_sram_data(struct psp_context *psp, 460 + struct amdgpu_firmware_info *ucode, 461 + enum AMDGPU_UCODE_ID ucode_type) 462 + { 463 + int err = 0; 464 + unsigned int fw_sram_reg_val = 0; 465 + unsigned int fw_sram_addr_reg_offset = 0; 466 + unsigned int fw_sram_data_reg_offset = 0; 467 + unsigned int ucode_size; 468 + uint32_t *ucode_mem = NULL; 469 + struct amdgpu_device *adev = psp->adev; 470 + 471 + err = psp_v3_1_sram_map(&fw_sram_reg_val, &fw_sram_addr_reg_offset, 472 + &fw_sram_data_reg_offset, ucode_type); 473 + if (err) 474 + return false; 475 + 476 + WREG32(fw_sram_addr_reg_offset, fw_sram_reg_val); 477 + 478 + ucode_size = ucode->ucode_size; 479 + ucode_mem = (uint32_t *)ucode->kaddr; 480 + while (!ucode_size) { 481 + fw_sram_reg_val = RREG32(fw_sram_data_reg_offset); 482 + 483 + if (*ucode_mem != fw_sram_reg_val) 484 + return false; 485 + 486 + ucode_mem++; 487 + /* 4 bytes */ 488 + ucode_size -= 4; 489 + } 490 + 491 + return true; 492 + } 493 + 494 + bool psp_v3_1_smu_reload_quirk(struct psp_context *psp) 495 + { 496 + struct amdgpu_device *adev = psp->adev; 497 + uint32_t reg, reg_val; 498 + 499 + reg_val = (smnMP1_FIRMWARE_FLAGS & 0xffffffff) | 0x03b00000; 500 + WREG32(SOC15_REG_OFFSET(NBIO, 0, mmPCIE_INDEX2), reg_val); 501 + reg = RREG32(SOC15_REG_OFFSET(NBIO, 0, mmPCIE_DATA2)); 502 + if ((reg & MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED_MASK) >> 503 + MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED__SHIFT) 504 + return true; 505 + 506 + return false; 507 + }
+50
drivers/gpu/drm/amd/amdgpu/psp_v3_1.h
··· 1 + /* 2 + * Copyright 2016 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 + * Author: Huang Rui 23 + * 24 + */ 25 + #ifndef __PSP_V3_1_H__ 26 + #define __PSP_V3_1_H__ 27 + 28 + #include "amdgpu_psp.h" 29 + 30 + enum { PSP_DIRECTORY_TABLE_ENTRIES = 4 }; 31 + enum { PSP_BINARY_ALIGNMENT = 64 }; 32 + enum { PSP_BOOTLOADER_1_MEG_ALIGNMENT = 0x100000 }; 33 + enum { PSP_BOOTLOADER_8_MEM_ALIGNMENT = 0x800000 }; 34 + 35 + extern int psp_v3_1_init_microcode(struct psp_context *psp); 36 + extern int psp_v3_1_bootloader_load_sysdrv(struct psp_context *psp); 37 + extern int psp_v3_1_bootloader_load_sos(struct psp_context *psp); 38 + extern int psp_v3_1_prep_cmd_buf(struct amdgpu_firmware_info *ucode, 39 + struct psp_gfx_cmd_resp *cmd); 40 + extern int psp_v3_1_ring_init(struct psp_context *psp, 41 + enum psp_ring_type ring_type); 42 + extern int psp_v3_1_cmd_submit(struct psp_context *psp, 43 + struct amdgpu_firmware_info *ucode, 44 + uint64_t cmd_buf_mc_addr, uint64_t fence_mc_addr, 45 + int index); 46 + extern bool psp_v3_1_compare_sram_data(struct psp_context *psp, 47 + struct amdgpu_firmware_info *ucode, 48 + enum AMDGPU_UCODE_ID ucode_type); 49 + extern bool psp_v3_1_smu_reload_quirk(struct psp_context *psp); 50 + #endif
+1
drivers/gpu/drm/amd/include/amd_shared.h
··· 68 68 AMD_IP_BLOCK_TYPE_GMC, 69 69 AMD_IP_BLOCK_TYPE_IH, 70 70 AMD_IP_BLOCK_TYPE_SMC, 71 + AMD_IP_BLOCK_TYPE_PSP, 71 72 AMD_IP_BLOCK_TYPE_DCE, 72 73 AMD_IP_BLOCK_TYPE_GFX, 73 74 AMD_IP_BLOCK_TYPE_SDMA,