blob: 9f83264ba9ebde2dadd91cef2c1e4872927b406e [file] [log] [blame]
Huang Rui0e5ca0d2017-03-03 18:37:23 -05001/*
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>
Masahiro Yamada248a1d62017-04-24 13:50:21 +090027#include <drm/drmP.h>
Huang Rui0e5ca0d2017-03-03 18:37:23 -050028#include "amdgpu.h"
29#include "amdgpu_psp.h"
30#include "amdgpu_ucode.h"
31#include "soc15_common.h"
32#include "psp_v3_1.h"
Huang Ruic1798b52016-12-16 10:08:48 +080033#include "psp_v10_0.h"
Huang Rui0e5ca0d2017-03-03 18:37:23 -050034
35static void psp_set_funcs(struct amdgpu_device *adev);
36
37static int psp_early_init(void *handle)
38{
39 struct amdgpu_device *adev = (struct amdgpu_device *)handle;
40
41 psp_set_funcs(adev);
42
43 return 0;
44}
45
46static int psp_sw_init(void *handle)
47{
48 struct amdgpu_device *adev = (struct amdgpu_device *)handle;
49 struct psp_context *psp = &adev->psp;
50 int ret;
51
52 switch (adev->asic_type) {
53 case CHIP_VEGA10:
54 psp->init_microcode = psp_v3_1_init_microcode;
55 psp->bootloader_load_sysdrv = psp_v3_1_bootloader_load_sysdrv;
56 psp->bootloader_load_sos = psp_v3_1_bootloader_load_sos;
57 psp->prep_cmd_buf = psp_v3_1_prep_cmd_buf;
58 psp->ring_init = psp_v3_1_ring_init;
Huang Ruibe70bbd2017-03-21 18:36:57 +080059 psp->ring_create = psp_v3_1_ring_create;
Trigger Huange3c5e982017-04-17 08:50:18 -040060 psp->ring_destroy = psp_v3_1_ring_destroy;
Huang Rui0e5ca0d2017-03-03 18:37:23 -050061 psp->cmd_submit = psp_v3_1_cmd_submit;
62 psp->compare_sram_data = psp_v3_1_compare_sram_data;
63 psp->smu_reload_quirk = psp_v3_1_smu_reload_quirk;
64 break;
Huang Ruic1798b52016-12-16 10:08:48 +080065 case CHIP_RAVEN:
Junwei Zhang6ab77112017-07-14 18:31:18 +080066 psp->init_microcode = psp_v10_0_init_microcode;
Huang Ruic1798b52016-12-16 10:08:48 +080067 psp->prep_cmd_buf = psp_v10_0_prep_cmd_buf;
68 psp->ring_init = psp_v10_0_ring_init;
Junwei Zhangccce0552017-07-14 18:34:48 +080069 psp->ring_create = psp_v10_0_ring_create;
Junwei Zhanga4f478b2017-07-14 18:37:44 +080070 psp->ring_destroy = psp_v10_0_ring_destroy;
Huang Ruic1798b52016-12-16 10:08:48 +080071 psp->cmd_submit = psp_v10_0_cmd_submit;
72 psp->compare_sram_data = psp_v10_0_compare_sram_data;
73 break;
Huang Rui0e5ca0d2017-03-03 18:37:23 -050074 default:
75 return -EINVAL;
76 }
77
78 psp->adev = adev;
79
80 ret = psp_init_microcode(psp);
81 if (ret) {
82 DRM_ERROR("Failed to load psp firmware!\n");
83 return ret;
84 }
85
86 return 0;
87}
88
89static int psp_sw_fini(void *handle)
90{
91 return 0;
92}
93
94int psp_wait_for(struct psp_context *psp, uint32_t reg_index,
95 uint32_t reg_val, uint32_t mask, bool check_changed)
96{
97 uint32_t val;
98 int i;
99 struct amdgpu_device *adev = psp->adev;
100
101 val = RREG32(reg_index);
102
103 for (i = 0; i < adev->usec_timeout; i++) {
104 if (check_changed) {
105 if (val != reg_val)
106 return 0;
107 } else {
108 if ((val & mask) == reg_val)
109 return 0;
110 }
111 udelay(1);
112 }
113
114 return -ETIME;
115}
116
117static int
118psp_cmd_submit_buf(struct psp_context *psp,
119 struct amdgpu_firmware_info *ucode,
120 struct psp_gfx_cmd_resp *cmd, uint64_t fence_mc_addr,
121 int index)
122{
123 int ret;
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500124
Huang Ruia1952da2017-06-11 18:57:08 +0800125 memset(psp->cmd_buf_mem, 0, PSP_CMD_BUFFER_SIZE);
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500126
Huang Ruia1952da2017-06-11 18:57:08 +0800127 memcpy(psp->cmd_buf_mem, cmd, sizeof(struct psp_gfx_cmd_resp));
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500128
Huang Ruia1952da2017-06-11 18:57:08 +0800129 ret = psp_cmd_submit(psp, ucode, psp->cmd_buf_mc_addr,
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500130 fence_mc_addr, index);
131
132 while (*((unsigned int *)psp->fence_buf) != index) {
133 msleep(1);
kbuild test robotca7f65c2017-03-31 18:15:10 +0800134 }
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500135
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500136 return ret;
137}
138
139static void psp_prep_tmr_cmd_buf(struct psp_gfx_cmd_resp *cmd,
140 uint64_t tmr_mc, uint32_t size)
141{
142 cmd->cmd_id = GFX_CMD_ID_SETUP_TMR;
Alex Deucherf03defe2017-06-22 18:26:33 -0400143 cmd->cmd.cmd_setup_tmr.buf_phy_addr_lo = lower_32_bits(tmr_mc);
144 cmd->cmd.cmd_setup_tmr.buf_phy_addr_hi = upper_32_bits(tmr_mc);
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500145 cmd->cmd.cmd_setup_tmr.buf_size = size;
146}
147
148/* Set up Trusted Memory Region */
149static int psp_tmr_init(struct psp_context *psp)
150{
151 int ret;
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500152
153 /*
154 * Allocate 3M memory aligned to 1M from Frame Buffer (local
155 * physical).
156 *
157 * Note: this memory need be reserved till the driver
158 * uninitializes.
159 */
160 ret = amdgpu_bo_create_kernel(psp->adev, 0x300000, 0x100000,
161 AMDGPU_GEM_DOMAIN_VRAM,
162 &psp->tmr_bo, &psp->tmr_mc_addr, &psp->tmr_buf);
Huang Rui6f2b1fc2017-03-21 16:18:11 +0800163
164 return ret;
165}
166
167static int psp_tmr_load(struct psp_context *psp)
168{
169 int ret;
170 struct psp_gfx_cmd_resp *cmd;
171
172 cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
173 if (!cmd)
174 return -ENOMEM;
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500175
176 psp_prep_tmr_cmd_buf(cmd, psp->tmr_mc_addr, 0x300000);
177
178 ret = psp_cmd_submit_buf(psp, NULL, cmd,
179 psp->fence_buf_mc_addr, 1);
180 if (ret)
Huang Rui6f2b1fc2017-03-21 16:18:11 +0800181 goto failed;
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500182
183 kfree(cmd);
184
185 return 0;
186
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500187failed:
188 kfree(cmd);
189 return ret;
190}
191
192static 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
Huang Ruif5cfef92017-03-21 18:02:04 +0800206static int psp_asd_init(struct psp_context *psp)
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500207{
208 int ret;
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500209
210 /*
211 * Allocate 16k memory aligned to 4k from Frame Buffer (local
212 * physical) for shared ASD <-> Driver
213 */
Huang Ruif5cfef92017-03-21 18:02:04 +0800214 ret = amdgpu_bo_create_kernel(psp->adev, PSP_ASD_SHARED_MEM_SIZE,
215 PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM,
216 &psp->asd_shared_bo,
217 &psp->asd_shared_mc_addr,
218 &psp->asd_shared_buf);
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500219
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500220 return ret;
221}
222
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500223static int psp_asd_load(struct psp_context *psp)
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500224{
225 int ret;
226 struct psp_gfx_cmd_resp *cmd;
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500227
Xiangliang Yu943cafb2017-05-04 11:05:13 +0800228 /* If PSP version doesn't match ASD version, asd loading will be failed.
229 * add workaround to bypass it for sriov now.
230 * TODO: add version check to make it common
231 */
232 if (amdgpu_sriov_vf(psp->adev))
233 return 0;
234
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500235 cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
236 if (!cmd)
237 return -ENOMEM;
238
Huang Rui2b0c3ae2017-03-22 10:16:05 +0800239 memset(psp->fw_pri_buf, 0, PSP_1_MEG);
240 memcpy(psp->fw_pri_buf, psp->asd_start_addr, psp->asd_ucode_size);
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500241
Huang Ruif5cfef92017-03-21 18:02:04 +0800242 psp_prep_asd_cmd_buf(cmd, psp->fw_pri_mc_addr, psp->asd_shared_mc_addr,
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500243 psp->asd_ucode_size, PSP_ASD_SHARED_MEM_SIZE);
244
245 ret = psp_cmd_submit_buf(psp, NULL, cmd,
246 psp->fence_buf_mc_addr, 2);
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500247
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500248 kfree(cmd);
249
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500250 return ret;
251}
252
Huang Ruibe70bbd2017-03-21 18:36:57 +0800253static int psp_hw_start(struct psp_context *psp)
254{
255 int ret;
256
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500257 ret = psp_bootloader_load_sysdrv(psp);
258 if (ret)
Huang Ruibe70bbd2017-03-21 18:36:57 +0800259 return ret;
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500260
261 ret = psp_bootloader_load_sos(psp);
262 if (ret)
Huang Ruibe70bbd2017-03-21 18:36:57 +0800263 return ret;
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500264
Huang Ruibe70bbd2017-03-21 18:36:57 +0800265 ret = psp_ring_create(psp, PSP_RING_TYPE__KM);
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500266 if (ret)
Huang Ruibe70bbd2017-03-21 18:36:57 +0800267 return ret;
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500268
Huang Ruibe70bbd2017-03-21 18:36:57 +0800269 ret = psp_tmr_load(psp);
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500270 if (ret)
Huang Ruibe70bbd2017-03-21 18:36:57 +0800271 return ret;
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500272
273 ret = psp_asd_load(psp);
274 if (ret)
Huang Ruibe70bbd2017-03-21 18:36:57 +0800275 return ret;
276
277 return 0;
278}
279
280static int psp_np_fw_load(struct psp_context *psp)
281{
282 int i, ret;
283 struct amdgpu_firmware_info *ucode;
284 struct amdgpu_device* adev = psp->adev;
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500285
286 for (i = 0; i < adev->firmware.max_ucodes; i++) {
287 ucode = &adev->firmware.ucode[i];
288 if (!ucode->fw)
289 continue;
290
291 if (ucode->ucode_id == AMDGPU_UCODE_ID_SMC &&
292 psp_smu_reload_quirk(psp))
293 continue;
Daniel Wange993ca42017-04-20 11:45:09 +0800294 if (amdgpu_sriov_vf(adev) &&
295 (ucode->ucode_id == AMDGPU_UCODE_ID_SDMA0
296 || ucode->ucode_id == AMDGPU_UCODE_ID_SDMA1
297 || ucode->ucode_id == AMDGPU_UCODE_ID_RLC_G))
298 /*skip ucode loading in SRIOV VF */
299 continue;
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500300
Huang Ruibe70bbd2017-03-21 18:36:57 +0800301 ret = psp_prep_cmd_buf(ucode, psp->cmd);
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500302 if (ret)
Huang Ruibe70bbd2017-03-21 18:36:57 +0800303 return ret;
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500304
Huang Ruibe70bbd2017-03-21 18:36:57 +0800305 ret = psp_cmd_submit_buf(psp, ucode, psp->cmd,
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500306 psp->fence_buf_mc_addr, i + 3);
307 if (ret)
Huang Ruibe70bbd2017-03-21 18:36:57 +0800308 return ret;
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500309
310#if 0
311 /* check if firmware loaded sucessfully */
312 if (!amdgpu_psp_check_fw_loading_status(adev, i))
313 return -EINVAL;
314#endif
315 }
316
Huang Ruibe70bbd2017-03-21 18:36:57 +0800317 return 0;
318}
319
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500320static int psp_load_fw(struct amdgpu_device *adev)
321{
322 int ret;
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500323 struct psp_context *psp = &adev->psp;
324
Huang Rui67bef0f2017-06-29 14:21:49 +0800325 psp->cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
326 if (!psp->cmd)
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500327 return -ENOMEM;
328
Huang Rui53a5cf52017-03-21 16:51:00 +0800329 ret = amdgpu_bo_create_kernel(adev, PSP_1_MEG, PSP_1_MEG,
330 AMDGPU_GEM_DOMAIN_GTT,
331 &psp->fw_pri_bo,
332 &psp->fw_pri_mc_addr,
333 &psp->fw_pri_buf);
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500334 if (ret)
335 goto failed;
336
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500337 ret = amdgpu_bo_create_kernel(adev, PSP_FENCE_BUFFER_SIZE, PAGE_SIZE,
338 AMDGPU_GEM_DOMAIN_VRAM,
339 &psp->fence_buf_bo,
340 &psp->fence_buf_mc_addr,
341 &psp->fence_buf);
342 if (ret)
Huang Ruia1952da2017-06-11 18:57:08 +0800343 goto failed_mem2;
344
345 ret = amdgpu_bo_create_kernel(adev, PSP_CMD_BUFFER_SIZE, PAGE_SIZE,
346 AMDGPU_GEM_DOMAIN_VRAM,
347 &psp->cmd_buf_bo, &psp->cmd_buf_mc_addr,
348 (void **)&psp->cmd_buf_mem);
349 if (ret)
Huang Rui53a5cf52017-03-21 16:51:00 +0800350 goto failed_mem1;
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500351
352 memset(psp->fence_buf, 0, PSP_FENCE_BUFFER_SIZE);
353
Huang Ruibe70bbd2017-03-21 18:36:57 +0800354 ret = psp_ring_init(psp, PSP_RING_TYPE__KM);
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500355 if (ret)
Huang Ruia1952da2017-06-11 18:57:08 +0800356 goto failed_mem;
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500357
Huang Ruibe70bbd2017-03-21 18:36:57 +0800358 ret = psp_tmr_init(psp);
Huang Rui6f2b1fc2017-03-21 16:18:11 +0800359 if (ret)
360 goto failed_mem;
361
Huang Ruif5cfef92017-03-21 18:02:04 +0800362 ret = psp_asd_init(psp);
363 if (ret)
364 goto failed_mem;
365
Huang Ruibe70bbd2017-03-21 18:36:57 +0800366 ret = psp_hw_start(psp);
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500367 if (ret)
368 goto failed_mem;
369
Huang Ruibe70bbd2017-03-21 18:36:57 +0800370 ret = psp_np_fw_load(psp);
371 if (ret)
372 goto failed_mem;
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500373
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500374 return 0;
375
376failed_mem:
Huang Ruia1952da2017-06-11 18:57:08 +0800377 amdgpu_bo_free_kernel(&psp->cmd_buf_bo,
378 &psp->cmd_buf_mc_addr,
379 (void **)&psp->cmd_buf_mem);
380failed_mem1:
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500381 amdgpu_bo_free_kernel(&psp->fence_buf_bo,
382 &psp->fence_buf_mc_addr, &psp->fence_buf);
Huang Ruia1952da2017-06-11 18:57:08 +0800383failed_mem2:
Huang Rui53a5cf52017-03-21 16:51:00 +0800384 amdgpu_bo_free_kernel(&psp->fw_pri_bo,
385 &psp->fw_pri_mc_addr, &psp->fw_pri_buf);
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500386failed:
Huang Rui67bef0f2017-06-29 14:21:49 +0800387 kfree(psp->cmd);
388 psp->cmd = NULL;
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500389 return ret;
390}
391
392static int psp_hw_init(void *handle)
393{
394 int ret;
395 struct amdgpu_device *adev = (struct amdgpu_device *)handle;
396
397
398 if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
399 return 0;
400
401 mutex_lock(&adev->firmware.mutex);
402 /*
403 * This sequence is just used on hw_init only once, no need on
404 * resume.
405 */
406 ret = amdgpu_ucode_init_bo(adev);
407 if (ret)
408 goto failed;
409
410 ret = psp_load_fw(adev);
411 if (ret) {
412 DRM_ERROR("PSP firmware loading failed\n");
413 goto failed;
414 }
415
416 mutex_unlock(&adev->firmware.mutex);
417 return 0;
418
419failed:
420 adev->firmware.load_type = AMDGPU_FW_LOAD_DIRECT;
421 mutex_unlock(&adev->firmware.mutex);
422 return -EINVAL;
423}
424
425static int psp_hw_fini(void *handle)
426{
427 struct amdgpu_device *adev = (struct amdgpu_device *)handle;
428 struct psp_context *psp = &adev->psp;
429
Trigger Huange3c5e982017-04-17 08:50:18 -0400430 if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
431 return 0;
432
433 amdgpu_ucode_fini_bo(adev);
434
435 psp_ring_destroy(psp, PSP_RING_TYPE__KM);
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500436
Huang Ruiedc4d3d2017-06-02 10:42:28 +0800437 amdgpu_bo_free_kernel(&psp->tmr_bo, &psp->tmr_mc_addr, &psp->tmr_buf);
438 amdgpu_bo_free_kernel(&psp->fw_pri_bo,
439 &psp->fw_pri_mc_addr, &psp->fw_pri_buf);
440 amdgpu_bo_free_kernel(&psp->fence_buf_bo,
441 &psp->fence_buf_mc_addr, &psp->fence_buf);
Huang Rui311146c2017-06-11 18:28:00 +0800442 amdgpu_bo_free_kernel(&psp->asd_shared_bo, &psp->asd_shared_mc_addr,
443 &psp->asd_shared_buf);
Huang Ruia1952da2017-06-11 18:57:08 +0800444 amdgpu_bo_free_kernel(&psp->cmd_buf_bo, &psp->cmd_buf_mc_addr,
445 (void **)&psp->cmd_buf_mem);
Huang Ruib4de2c52017-04-10 15:29:42 +0800446
Huang Rui67bef0f2017-06-29 14:21:49 +0800447 kfree(psp->cmd);
448 psp->cmd = NULL;
449
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500450 return 0;
451}
452
453static int psp_suspend(void *handle)
454{
455 return 0;
456}
457
458static int psp_resume(void *handle)
459{
460 int ret;
461 struct amdgpu_device *adev = (struct amdgpu_device *)handle;
Huang Rui93ea9b92017-03-23 11:20:25 +0800462 struct psp_context *psp = &adev->psp;
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500463
464 if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
465 return 0;
466
Huang Rui93ea9b92017-03-23 11:20:25 +0800467 DRM_INFO("PSP is resuming...\n");
468
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500469 mutex_lock(&adev->firmware.mutex);
470
Huang Rui93ea9b92017-03-23 11:20:25 +0800471 ret = psp_hw_start(psp);
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500472 if (ret)
Huang Rui93ea9b92017-03-23 11:20:25 +0800473 goto failed;
474
475 ret = psp_np_fw_load(psp);
476 if (ret)
477 goto failed;
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500478
479 mutex_unlock(&adev->firmware.mutex);
480
Huang Rui93ea9b92017-03-23 11:20:25 +0800481 return 0;
482
483failed:
484 DRM_ERROR("PSP resume failed\n");
485 mutex_unlock(&adev->firmware.mutex);
Huang Rui0e5ca0d2017-03-03 18:37:23 -0500486 return ret;
487}
488
489static bool psp_check_fw_loading_status(struct amdgpu_device *adev,
490 enum AMDGPU_UCODE_ID ucode_type)
491{
492 struct amdgpu_firmware_info *ucode = NULL;
493
494 if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) {
495 DRM_INFO("firmware is not loaded by PSP\n");
496 return true;
497 }
498
499 if (!adev->firmware.fw_size)
500 return false;
501
502 ucode = &adev->firmware.ucode[ucode_type];
503 if (!ucode->fw || !ucode->ucode_size)
504 return false;
505
506 return psp_compare_sram_data(&adev->psp, ucode, ucode_type);
507}
508
509static int psp_set_clockgating_state(void *handle,
510 enum amd_clockgating_state state)
511{
512 return 0;
513}
514
515static int psp_set_powergating_state(void *handle,
516 enum amd_powergating_state state)
517{
518 return 0;
519}
520
521const struct amd_ip_funcs psp_ip_funcs = {
522 .name = "psp",
523 .early_init = psp_early_init,
524 .late_init = NULL,
525 .sw_init = psp_sw_init,
526 .sw_fini = psp_sw_fini,
527 .hw_init = psp_hw_init,
528 .hw_fini = psp_hw_fini,
529 .suspend = psp_suspend,
530 .resume = psp_resume,
531 .is_idle = NULL,
532 .wait_for_idle = NULL,
533 .soft_reset = NULL,
534 .set_clockgating_state = psp_set_clockgating_state,
535 .set_powergating_state = psp_set_powergating_state,
536};
537
538static const struct amdgpu_psp_funcs psp_funcs = {
539 .check_fw_loading_status = psp_check_fw_loading_status,
540};
541
542static void psp_set_funcs(struct amdgpu_device *adev)
543{
544 if (NULL == adev->firmware.funcs)
545 adev->firmware.funcs = &psp_funcs;
546}
547
548const struct amdgpu_ip_block_version psp_v3_1_ip_block =
549{
550 .type = AMD_IP_BLOCK_TYPE_PSP,
551 .major = 3,
552 .minor = 1,
553 .rev = 0,
554 .funcs = &psp_ip_funcs,
555};
Huang Ruidfbd6432016-12-16 10:01:55 +0800556
557const struct amdgpu_ip_block_version psp_v10_0_ip_block =
558{
559 .type = AMD_IP_BLOCK_TYPE_PSP,
560 .major = 10,
561 .minor = 0,
562 .rev = 0,
563 .funcs = &psp_ip_funcs,
564};