Commit | Line | Data |
---|---|---|
654f761c FX |
1 | /* |
2 | * Copyright 2018 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 | #include <linux/firmware.h> | |
f867723b | 24 | #include <linux/module.h> |
7044cb6c | 25 | #include <linux/vmalloc.h> |
f867723b | 26 | |
654f761c FX |
27 | #include "amdgpu.h" |
28 | #include "amdgpu_psp.h" | |
c2c6f816 | 29 | #include "amdgpu_ras.h" |
654f761c FX |
30 | #include "amdgpu_ucode.h" |
31 | #include "soc15_common.h" | |
32 | #include "psp_v11_0.h" | |
33 | ||
34 | #include "mp/mp_11_0_offset.h" | |
35 | #include "mp/mp_11_0_sh_mask.h" | |
36 | #include "gc/gc_9_0_offset.h" | |
37 | #include "sdma0/sdma0_4_0_offset.h" | |
38 | #include "nbio/nbio_7_4_offset.h" | |
39 | ||
b849aaa4 CK |
40 | #include "oss/osssys_4_0_offset.h" |
41 | #include "oss/osssys_4_0_sh_mask.h" | |
42 | ||
654f761c | 43 | MODULE_FIRMWARE("amdgpu/vega20_sos.bin"); |
06d6370e | 44 | MODULE_FIRMWARE("amdgpu/vega20_asd.bin"); |
51e7177f | 45 | MODULE_FIRMWARE("amdgpu/vega20_ta.bin"); |
bc290fe5 | 46 | MODULE_FIRMWARE("amdgpu/navi10_sos.bin"); |
a698faf8 | 47 | MODULE_FIRMWARE("amdgpu/navi10_asd.bin"); |
a2e4b418 | 48 | MODULE_FIRMWARE("amdgpu/navi10_ta.bin"); |
82522b2d | 49 | MODULE_FIRMWARE("amdgpu/navi14_sos.bin"); |
8687b47e | 50 | MODULE_FIRMWARE("amdgpu/navi14_asd.bin"); |
a2e4b418 | 51 | MODULE_FIRMWARE("amdgpu/navi14_ta.bin"); |
739cdbd6 XY |
52 | MODULE_FIRMWARE("amdgpu/navi12_sos.bin"); |
53 | MODULE_FIRMWARE("amdgpu/navi12_asd.bin"); | |
a2e4b418 | 54 | MODULE_FIRMWARE("amdgpu/navi12_ta.bin"); |
f36d9ab9 JC |
55 | MODULE_FIRMWARE("amdgpu/arcturus_sos.bin"); |
56 | MODULE_FIRMWARE("amdgpu/arcturus_asd.bin"); | |
4fb60b02 | 57 | MODULE_FIRMWARE("amdgpu/arcturus_ta.bin"); |
344fed0b | 58 | MODULE_FIRMWARE("amdgpu/sienna_cichlid_sos.bin"); |
6ece96a1 | 59 | MODULE_FIRMWARE("amdgpu/sienna_cichlid_ta.bin"); |
c82b38ec | 60 | MODULE_FIRMWARE("amdgpu/navy_flounder_sos.bin"); |
24b763d0 | 61 | MODULE_FIRMWARE("amdgpu/navy_flounder_ta.bin"); |
ed3b7353 HR |
62 | MODULE_FIRMWARE("amdgpu/vangogh_asd.bin"); |
63 | MODULE_FIRMWARE("amdgpu/vangogh_toc.bin"); | |
462c272b | 64 | MODULE_FIRMWARE("amdgpu/dimgrey_cavefish_sos.bin"); |
2bdb8302 | 65 | MODULE_FIRMWARE("amdgpu/dimgrey_cavefish_ta.bin"); |
654f761c FX |
66 | |
67 | /* address block */ | |
68 | #define smnMP1_FIRMWARE_FLAGS 0x3010024 | |
bc290fe5 TZ |
69 | /* navi10 reg offset define */ |
70 | #define mmRLC_GPM_UCODE_ADDR_NV10 0x5b61 | |
71 | #define mmRLC_GPM_UCODE_DATA_NV10 0x5b62 | |
72 | #define mmSDMA0_UCODE_ADDR_NV10 0x5880 | |
73 | #define mmSDMA0_UCODE_DATA_NV10 0x5881 | |
367039bf TY |
74 | /* memory training timeout define */ |
75 | #define MEM_TRAIN_SEND_MSG_TIMEOUT_US 3000000 | |
654f761c | 76 | |
0dc93fd1 AG |
77 | /* For large FW files the time to complete can be very long */ |
78 | #define USBC_PD_POLLING_LIMIT_S 240 | |
79 | ||
654f761c FX |
80 | static int psp_v11_0_init_microcode(struct psp_context *psp) |
81 | { | |
82 | struct amdgpu_device *adev = psp->adev; | |
83 | const char *chip_name; | |
0a305e34 | 84 | char fw_name[PSP_FW_NAME_LEN]; |
654f761c | 85 | int err = 0; |
51e7177f | 86 | const struct ta_firmware_header_v1_0 *ta_hdr; |
654f761c FX |
87 | |
88 | DRM_DEBUG("\n"); | |
89 | ||
90 | switch (adev->asic_type) { | |
91 | case CHIP_VEGA20: | |
92 | chip_name = "vega20"; | |
93 | break; | |
bc290fe5 TZ |
94 | case CHIP_NAVI10: |
95 | chip_name = "navi10"; | |
96 | break; | |
82522b2d XY |
97 | case CHIP_NAVI14: |
98 | chip_name = "navi14"; | |
99 | break; | |
739cdbd6 XY |
100 | case CHIP_NAVI12: |
101 | chip_name = "navi12"; | |
102 | break; | |
dc0d9622 JC |
103 | case CHIP_ARCTURUS: |
104 | chip_name = "arcturus"; | |
105 | break; | |
344fed0b LG |
106 | case CHIP_SIENNA_CICHLID: |
107 | chip_name = "sienna_cichlid"; | |
108 | break; | |
c82b38ec JC |
109 | case CHIP_NAVY_FLOUNDER: |
110 | chip_name = "navy_flounder"; | |
111 | break; | |
ed3b7353 HR |
112 | case CHIP_VANGOGH: |
113 | chip_name = "vangogh"; | |
114 | break; | |
462c272b TZ |
115 | case CHIP_DIMGREY_CAVEFISH: |
116 | chip_name = "dimgrey_cavefish"; | |
117 | break; | |
654f761c FX |
118 | default: |
119 | BUG(); | |
120 | } | |
121 | ||
06d6370e | 122 | |
a954f3ff HZ |
123 | switch (adev->asic_type) { |
124 | case CHIP_VEGA20: | |
4fb60b02 | 125 | case CHIP_ARCTURUS: |
5120cb54 HR |
126 | err = psp_init_sos_microcode(psp, chip_name); |
127 | if (err) | |
128 | return err; | |
129 | err = psp_init_asd_microcode(psp, chip_name); | |
130 | if (err) | |
131 | return err; | |
a954f3ff HZ |
132 | snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ta.bin", chip_name); |
133 | err = request_firmware(&adev->psp.ta_fw, fw_name, adev->dev); | |
134 | if (err) { | |
135 | release_firmware(adev->psp.ta_fw); | |
136 | adev->psp.ta_fw = NULL; | |
137 | dev_info(adev->dev, | |
138 | "psp v11.0: Failed to load firmware \"%s\"\n", fw_name); | |
139 | } else { | |
140 | err = amdgpu_ucode_validate(adev->psp.ta_fw); | |
141 | if (err) | |
142 | goto out2; | |
143 | ||
144 | ta_hdr = (const struct ta_firmware_header_v1_0 *)adev->psp.ta_fw->data; | |
145 | adev->psp.ta_xgmi_ucode_version = le32_to_cpu(ta_hdr->ta_xgmi_ucode_version); | |
146 | adev->psp.ta_xgmi_ucode_size = le32_to_cpu(ta_hdr->ta_xgmi_size_bytes); | |
147 | adev->psp.ta_xgmi_start_addr = (uint8_t *)ta_hdr + | |
148 | le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes); | |
149 | adev->psp.ta_fw_version = le32_to_cpu(ta_hdr->header.ucode_version); | |
150 | adev->psp.ta_ras_ucode_version = le32_to_cpu(ta_hdr->ta_ras_ucode_version); | |
151 | adev->psp.ta_ras_ucode_size = le32_to_cpu(ta_hdr->ta_ras_size_bytes); | |
152 | adev->psp.ta_ras_start_addr = (uint8_t *)adev->psp.ta_xgmi_start_addr + | |
153 | le32_to_cpu(ta_hdr->ta_ras_offset_bytes); | |
154 | } | |
155 | break; | |
156 | case CHIP_NAVI10: | |
e470d287 | 157 | case CHIP_NAVI14: |
739cdbd6 | 158 | case CHIP_NAVI12: |
5120cb54 HR |
159 | err = psp_init_sos_microcode(psp, chip_name); |
160 | if (err) | |
161 | return err; | |
162 | err = psp_init_asd_microcode(psp, chip_name); | |
163 | if (err) | |
164 | return err; | |
1a0f3667 ML |
165 | if (amdgpu_sriov_vf(adev)) |
166 | break; | |
a7f4ba7a BL |
167 | snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ta.bin", chip_name); |
168 | err = request_firmware(&adev->psp.ta_fw, fw_name, adev->dev); | |
169 | if (err) { | |
170 | release_firmware(adev->psp.ta_fw); | |
171 | adev->psp.ta_fw = NULL; | |
172 | dev_info(adev->dev, | |
173 | "psp v11.0: Failed to load firmware \"%s\"\n", fw_name); | |
174 | } else { | |
175 | err = amdgpu_ucode_validate(adev->psp.ta_fw); | |
176 | if (err) | |
177 | goto out2; | |
178 | ||
179 | ta_hdr = (const struct ta_firmware_header_v1_0 *)adev->psp.ta_fw->data; | |
180 | adev->psp.ta_hdcp_ucode_version = le32_to_cpu(ta_hdr->ta_hdcp_ucode_version); | |
181 | adev->psp.ta_hdcp_ucode_size = le32_to_cpu(ta_hdr->ta_hdcp_size_bytes); | |
182 | adev->psp.ta_hdcp_start_addr = (uint8_t *)ta_hdr + | |
183 | le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes); | |
184 | ||
185 | adev->psp.ta_fw_version = le32_to_cpu(ta_hdr->header.ucode_version); | |
186 | ||
187 | adev->psp.ta_dtm_ucode_version = le32_to_cpu(ta_hdr->ta_dtm_ucode_version); | |
188 | adev->psp.ta_dtm_ucode_size = le32_to_cpu(ta_hdr->ta_dtm_size_bytes); | |
189 | adev->psp.ta_dtm_start_addr = (uint8_t *)adev->psp.ta_hdcp_start_addr + | |
190 | le32_to_cpu(ta_hdr->ta_dtm_offset_bytes); | |
191 | } | |
a954f3ff | 192 | break; |
344fed0b | 193 | case CHIP_SIENNA_CICHLID: |
0a668aee | 194 | case CHIP_NAVY_FLOUNDER: |
2bdb8302 | 195 | case CHIP_DIMGREY_CAVEFISH: |
5120cb54 HR |
196 | err = psp_init_sos_microcode(psp, chip_name); |
197 | if (err) | |
198 | return err; | |
2bdb8302 | 199 | err = psp_init_ta_microcode(psp, chip_name); |
462c272b TZ |
200 | if (err) |
201 | return err; | |
202 | break; | |
5120cb54 HR |
203 | case CHIP_VANGOGH: |
204 | err = psp_init_asd_microcode(psp, chip_name); | |
205 | if (err) | |
206 | return err; | |
207 | err = psp_init_toc_microcode(psp, chip_name); | |
208 | if (err) | |
209 | return err; | |
6ece96a1 | 210 | break; |
a954f3ff HZ |
211 | default: |
212 | BUG(); | |
1d69511e | 213 | } |
51e7177f | 214 | |
654f761c | 215 | return 0; |
06d6370e EQ |
216 | |
217 | out2: | |
218 | release_firmware(adev->psp.ta_fw); | |
219 | adev->psp.ta_fw = NULL; | |
654f761c FX |
220 | return err; |
221 | } | |
222 | ||
3fdd2da0 | 223 | static int psp_v11_0_wait_for_bootloader(struct psp_context *psp) |
097dc53e JC |
224 | { |
225 | struct amdgpu_device *adev = psp->adev; | |
226 | ||
227 | int ret; | |
228 | int retry_loop; | |
229 | ||
230 | for (retry_loop = 0; retry_loop < 10; retry_loop++) { | |
231 | /* Wait for bootloader to signify that is | |
232 | ready having bit 31 of C2PMSG_35 set to 1 */ | |
233 | ret = psp_wait_for(psp, | |
234 | SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_35), | |
235 | 0x80000000, | |
236 | 0x80000000, | |
237 | false); | |
238 | ||
239 | if (ret == 0) | |
240 | return 0; | |
241 | } | |
242 | ||
243 | return ret; | |
244 | } | |
245 | ||
a7d4c920 TY |
246 | static bool psp_v11_0_is_sos_alive(struct psp_context *psp) |
247 | { | |
248 | struct amdgpu_device *adev = psp->adev; | |
249 | uint32_t sol_reg; | |
250 | ||
251 | sol_reg = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_81); | |
252 | ||
253 | return sol_reg != 0x0; | |
254 | } | |
255 | ||
42989359 HZ |
256 | static int psp_v11_0_bootloader_load_kdb(struct psp_context *psp) |
257 | { | |
258 | int ret; | |
259 | uint32_t psp_gfxdrv_command_reg = 0; | |
260 | struct amdgpu_device *adev = psp->adev; | |
42989359 HZ |
261 | |
262 | /* Check tOS sign of life register to confirm sys driver and sOS | |
263 | * are already been loaded. | |
264 | */ | |
d4d27897 | 265 | if (psp_v11_0_is_sos_alive(psp)) |
42989359 | 266 | return 0; |
42989359 | 267 | |
097dc53e | 268 | ret = psp_v11_0_wait_for_bootloader(psp); |
42989359 HZ |
269 | if (ret) |
270 | return ret; | |
271 | ||
272 | memset(psp->fw_pri_buf, 0, PSP_1_MEG); | |
273 | ||
274 | /* Copy PSP KDB binary to memory */ | |
275 | memcpy(psp->fw_pri_buf, psp->kdb_start_addr, psp->kdb_bin_size); | |
276 | ||
73469970 | 277 | /* Provide the PSP KDB to bootloader */ |
42989359 HZ |
278 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36, |
279 | (uint32_t)(psp->fw_pri_mc_addr >> 20)); | |
280 | psp_gfxdrv_command_reg = PSP_BL__LOAD_KEY_DATABASE; | |
281 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_35, | |
282 | psp_gfxdrv_command_reg); | |
283 | ||
097dc53e | 284 | ret = psp_v11_0_wait_for_bootloader(psp); |
42989359 HZ |
285 | |
286 | return ret; | |
287 | } | |
288 | ||
70509057 LG |
289 | static int psp_v11_0_bootloader_load_spl(struct psp_context *psp) |
290 | { | |
291 | int ret; | |
292 | uint32_t psp_gfxdrv_command_reg = 0; | |
293 | struct amdgpu_device *adev = psp->adev; | |
294 | ||
295 | /* Check tOS sign of life register to confirm sys driver and sOS | |
296 | * are already been loaded. | |
297 | */ | |
298 | if (psp_v11_0_is_sos_alive(psp)) | |
299 | return 0; | |
300 | ||
301 | ret = psp_v11_0_wait_for_bootloader(psp); | |
302 | if (ret) | |
303 | return ret; | |
304 | ||
305 | memset(psp->fw_pri_buf, 0, PSP_1_MEG); | |
306 | ||
307 | /* Copy PSP SPL binary to memory */ | |
308 | memcpy(psp->fw_pri_buf, psp->spl_start_addr, psp->spl_bin_size); | |
309 | ||
310 | /* Provide the PSP SPL to bootloader */ | |
311 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36, | |
312 | (uint32_t)(psp->fw_pri_mc_addr >> 20)); | |
313 | psp_gfxdrv_command_reg = PSP_BL__LOAD_TOS_SPL_TABLE; | |
314 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_35, | |
315 | psp_gfxdrv_command_reg); | |
316 | ||
317 | ret = psp_v11_0_wait_for_bootloader(psp); | |
318 | ||
319 | return ret; | |
320 | } | |
321 | ||
654f761c FX |
322 | static int psp_v11_0_bootloader_load_sysdrv(struct psp_context *psp) |
323 | { | |
324 | int ret; | |
325 | uint32_t psp_gfxdrv_command_reg = 0; | |
326 | struct amdgpu_device *adev = psp->adev; | |
654f761c FX |
327 | |
328 | /* Check sOS sign of life register to confirm sys driver and sOS | |
329 | * are already been loaded. | |
330 | */ | |
d4d27897 | 331 | if (psp_v11_0_is_sos_alive(psp)) |
654f761c FX |
332 | return 0; |
333 | ||
097dc53e | 334 | ret = psp_v11_0_wait_for_bootloader(psp); |
654f761c FX |
335 | if (ret) |
336 | return ret; | |
337 | ||
338 | memset(psp->fw_pri_buf, 0, PSP_1_MEG); | |
339 | ||
340 | /* Copy PSP System Driver binary to memory */ | |
341 | memcpy(psp->fw_pri_buf, psp->sys_start_addr, psp->sys_bin_size); | |
342 | ||
548f2ecc | 343 | /* Provide the sys driver to bootloader */ |
654f761c FX |
344 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36, |
345 | (uint32_t)(psp->fw_pri_mc_addr >> 20)); | |
3840fe25 | 346 | psp_gfxdrv_command_reg = PSP_BL__LOAD_SYSDRV; |
654f761c FX |
347 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_35, |
348 | psp_gfxdrv_command_reg); | |
349 | ||
350 | /* there might be handshake issue with hardware which needs delay */ | |
351 | mdelay(20); | |
352 | ||
097dc53e | 353 | ret = psp_v11_0_wait_for_bootloader(psp); |
654f761c FX |
354 | |
355 | return ret; | |
356 | } | |
357 | ||
358 | static int psp_v11_0_bootloader_load_sos(struct psp_context *psp) | |
359 | { | |
360 | int ret; | |
361 | unsigned int psp_gfxdrv_command_reg = 0; | |
362 | struct amdgpu_device *adev = psp->adev; | |
654f761c FX |
363 | |
364 | /* Check sOS sign of life register to confirm sys driver and sOS | |
365 | * are already been loaded. | |
366 | */ | |
a7d4c920 | 367 | if (psp_v11_0_is_sos_alive(psp)) |
654f761c FX |
368 | return 0; |
369 | ||
097dc53e | 370 | ret = psp_v11_0_wait_for_bootloader(psp); |
654f761c FX |
371 | if (ret) |
372 | return ret; | |
373 | ||
374 | memset(psp->fw_pri_buf, 0, PSP_1_MEG); | |
375 | ||
376 | /* Copy Secure OS binary to PSP memory */ | |
377 | memcpy(psp->fw_pri_buf, psp->sos_start_addr, psp->sos_bin_size); | |
378 | ||
548f2ecc | 379 | /* Provide the PSP secure OS to bootloader */ |
654f761c FX |
380 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36, |
381 | (uint32_t)(psp->fw_pri_mc_addr >> 20)); | |
3840fe25 | 382 | psp_gfxdrv_command_reg = PSP_BL__LOAD_SOSDRV; |
654f761c FX |
383 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_35, |
384 | psp_gfxdrv_command_reg); | |
385 | ||
386 | /* there might be handshake issue with hardware which needs delay */ | |
387 | mdelay(20); | |
388 | ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_81), | |
389 | RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_81), | |
390 | 0, true); | |
391 | ||
392 | return ret; | |
393 | } | |
394 | ||
654f761c FX |
395 | static int psp_v11_0_ring_init(struct psp_context *psp, |
396 | enum psp_ring_type ring_type) | |
397 | { | |
398 | int ret = 0; | |
399 | struct psp_ring *ring; | |
400 | struct amdgpu_device *adev = psp->adev; | |
401 | ||
402 | ring = &psp->km_ring; | |
403 | ||
404 | ring->ring_type = ring_type; | |
405 | ||
406 | /* allocate 4k Page of Local Frame Buffer memory for ring */ | |
407 | ring->ring_size = 0x1000; | |
408 | ret = amdgpu_bo_create_kernel(adev, ring->ring_size, PAGE_SIZE, | |
409 | AMDGPU_GEM_DOMAIN_VRAM, | |
410 | &adev->firmware.rbuf, | |
411 | &ring->ring_mem_mc_addr, | |
412 | (void **)&ring->ring_mem); | |
413 | if (ret) { | |
414 | ring->ring_size = 0; | |
415 | return ret; | |
416 | } | |
417 | ||
418 | return 0; | |
419 | } | |
420 | ||
51c0f58e JZ |
421 | static int psp_v11_0_ring_stop(struct psp_context *psp, |
422 | enum psp_ring_type ring_type) | |
423 | { | |
424 | int ret = 0; | |
425 | struct amdgpu_device *adev = psp->adev; | |
426 | ||
427 | /* Write the ring destroy command*/ | |
a2676149 | 428 | if (amdgpu_sriov_vf(adev)) |
51c0f58e JZ |
429 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_101, |
430 | GFX_CTRL_CMD_ID_DESTROY_GPCOM_RING); | |
431 | else | |
432 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_64, | |
433 | GFX_CTRL_CMD_ID_DESTROY_RINGS); | |
434 | ||
435 | /* there might be handshake issue with hardware which needs delay */ | |
436 | mdelay(20); | |
437 | ||
438 | /* Wait for response flag (bit 31) */ | |
a2676149 | 439 | if (amdgpu_sriov_vf(adev)) |
51c0f58e JZ |
440 | ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_101), |
441 | 0x80000000, 0x80000000, false); | |
442 | else | |
443 | ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64), | |
444 | 0x80000000, 0x80000000, false); | |
445 | ||
446 | return ret; | |
447 | } | |
448 | ||
654f761c FX |
449 | static int psp_v11_0_ring_create(struct psp_context *psp, |
450 | enum psp_ring_type ring_type) | |
451 | { | |
452 | int ret = 0; | |
453 | unsigned int psp_ring_reg = 0; | |
454 | struct psp_ring *ring = &psp->km_ring; | |
455 | struct amdgpu_device *adev = psp->adev; | |
456 | ||
a2676149 | 457 | if (amdgpu_sriov_vf(adev)) { |
51c0f58e JZ |
458 | ret = psp_v11_0_ring_stop(psp, ring_type); |
459 | if (ret) { | |
460 | DRM_ERROR("psp_v11_0_ring_stop_sriov failed!\n"); | |
461 | return ret; | |
462 | } | |
463 | ||
5ec996df XY |
464 | /* Write low address of the ring to C2PMSG_102 */ |
465 | psp_ring_reg = lower_32_bits(ring->ring_mem_mc_addr); | |
466 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_102, psp_ring_reg); | |
467 | /* Write high address of the ring to C2PMSG_103 */ | |
468 | psp_ring_reg = upper_32_bits(ring->ring_mem_mc_addr); | |
469 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_103, psp_ring_reg); | |
470 | ||
471 | /* Write the ring initialization command to C2PMSG_101 */ | |
472 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_101, | |
473 | GFX_CTRL_CMD_ID_INIT_GPCOM_RING); | |
474 | ||
475 | /* there might be handshake issue with hardware which needs delay */ | |
476 | mdelay(20); | |
477 | ||
478 | /* Wait for response flag (bit 31) in C2PMSG_101 */ | |
479 | ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_101), | |
480 | 0x80000000, 0x8000FFFF, false); | |
481 | ||
482 | } else { | |
d7e7f1ea XY |
483 | /* Wait for sOS ready for ring creation */ |
484 | ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64), | |
485 | 0x80000000, 0x80000000, false); | |
486 | if (ret) { | |
487 | DRM_ERROR("Failed to wait for sOS ready for ring creation\n"); | |
488 | return ret; | |
489 | } | |
490 | ||
5ec996df XY |
491 | /* Write low address of the ring to C2PMSG_69 */ |
492 | psp_ring_reg = lower_32_bits(ring->ring_mem_mc_addr); | |
493 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_69, psp_ring_reg); | |
494 | /* Write high address of the ring to C2PMSG_70 */ | |
495 | psp_ring_reg = upper_32_bits(ring->ring_mem_mc_addr); | |
496 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_70, psp_ring_reg); | |
497 | /* Write size of ring to C2PMSG_71 */ | |
498 | psp_ring_reg = ring->ring_size; | |
499 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_71, psp_ring_reg); | |
500 | /* Write the ring initialization command to C2PMSG_64 */ | |
501 | psp_ring_reg = ring_type; | |
502 | psp_ring_reg = psp_ring_reg << 16; | |
503 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_64, psp_ring_reg); | |
504 | ||
505 | /* there might be handshake issue with hardware which needs delay */ | |
506 | mdelay(20); | |
507 | ||
508 | /* Wait for response flag (bit 31) in C2PMSG_64 */ | |
509 | ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64), | |
510 | 0x80000000, 0x8000FFFF, false); | |
511 | } | |
654f761c FX |
512 | |
513 | return ret; | |
514 | } | |
515 | ||
654f761c FX |
516 | |
517 | static int psp_v11_0_ring_destroy(struct psp_context *psp, | |
518 | enum psp_ring_type ring_type) | |
519 | { | |
520 | int ret = 0; | |
521 | struct psp_ring *ring = &psp->km_ring; | |
522 | struct amdgpu_device *adev = psp->adev; | |
523 | ||
524 | ret = psp_v11_0_ring_stop(psp, ring_type); | |
525 | if (ret) | |
526 | DRM_ERROR("Fail to stop psp ring\n"); | |
527 | ||
528 | amdgpu_bo_free_kernel(&adev->firmware.rbuf, | |
529 | &ring->ring_mem_mc_addr, | |
530 | (void **)&ring->ring_mem); | |
531 | ||
532 | return ret; | |
533 | } | |
534 | ||
654f761c FX |
535 | static int psp_v11_0_mode1_reset(struct psp_context *psp) |
536 | { | |
537 | int ret; | |
538 | uint32_t offset; | |
539 | struct amdgpu_device *adev = psp->adev; | |
540 | ||
541 | offset = SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64); | |
542 | ||
543 | ret = psp_wait_for(psp, offset, 0x80000000, 0x8000FFFF, false); | |
544 | ||
545 | if (ret) { | |
546 | DRM_INFO("psp is not working correctly before mode1 reset!\n"); | |
547 | return -EINVAL; | |
548 | } | |
549 | ||
550 | /*send the mode 1 reset command*/ | |
551 | WREG32(offset, GFX_CTRL_CMD_ID_MODE1_RST); | |
552 | ||
38cd8a28 | 553 | msleep(500); |
654f761c FX |
554 | |
555 | offset = SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_33); | |
556 | ||
557 | ret = psp_wait_for(psp, offset, 0x80000000, 0x80000000, false); | |
558 | ||
559 | if (ret) { | |
560 | DRM_INFO("psp mode 1 reset failed!\n"); | |
561 | return -EINVAL; | |
562 | } | |
563 | ||
564 | DRM_INFO("psp mode1 reset succeed \n"); | |
565 | ||
566 | return 0; | |
567 | } | |
568 | ||
367039bf TY |
569 | static int psp_v11_0_memory_training_send_msg(struct psp_context *psp, int msg) |
570 | { | |
571 | int ret; | |
572 | int i; | |
573 | uint32_t data_32; | |
574 | int max_wait; | |
575 | struct amdgpu_device *adev = psp->adev; | |
576 | ||
577 | data_32 = (psp->mem_train_ctx.c2p_train_data_offset >> 20); | |
578 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36, data_32); | |
579 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_35, msg); | |
580 | ||
581 | max_wait = MEM_TRAIN_SEND_MSG_TIMEOUT_US / adev->usec_timeout; | |
582 | for (i = 0; i < max_wait; i++) { | |
583 | ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_35), | |
584 | 0x80000000, 0x80000000, false); | |
585 | if (ret == 0) | |
586 | break; | |
587 | } | |
588 | if (i < max_wait) | |
589 | ret = 0; | |
590 | else | |
591 | ret = -ETIME; | |
592 | ||
593 | DRM_DEBUG("training %s %s, cost %d @ %d ms\n", | |
594 | (msg == PSP_BL__DRAM_SHORT_TRAIN) ? "short" : "long", | |
595 | (ret == 0) ? "succeed" : "failed", | |
596 | i, adev->usec_timeout/1000); | |
597 | return ret; | |
598 | } | |
599 | ||
367039bf | 600 | /* |
4a497510 | 601 | * save and restore process |
367039bf TY |
602 | */ |
603 | static int psp_v11_0_memory_training(struct psp_context *psp, uint32_t ops) | |
604 | { | |
367039bf | 605 | struct psp_memory_training_context *ctx = &psp->mem_train_ctx; |
8acedab0 | 606 | uint32_t *pcache = (uint32_t *)ctx->sys_cache; |
240c811c TY |
607 | struct amdgpu_device *adev = psp->adev; |
608 | uint32_t p2c_header[4]; | |
609 | uint32_t sz; | |
610 | void *buf; | |
611 | int ret; | |
367039bf TY |
612 | |
613 | if (ctx->init == PSP_MEM_TRAIN_NOT_SUPPORT) { | |
614 | DRM_DEBUG("Memory training is not supported.\n"); | |
615 | return 0; | |
616 | } else if (ctx->init != PSP_MEM_TRAIN_INIT_SUCCESS) { | |
617 | DRM_ERROR("Memory training initialization failure.\n"); | |
618 | return -EINVAL; | |
619 | } | |
620 | ||
621 | if (psp_v11_0_is_sos_alive(psp)) { | |
622 | DRM_DEBUG("SOS is alive, skip memory training.\n"); | |
623 | return 0; | |
624 | } | |
625 | ||
240c811c | 626 | amdgpu_device_vram_access(adev, ctx->p2c_train_data_offset, p2c_header, sizeof(p2c_header), false); |
367039bf TY |
627 | DRM_DEBUG("sys_cache[%08x,%08x,%08x,%08x] p2c_header[%08x,%08x,%08x,%08x]\n", |
628 | pcache[0], pcache[1], pcache[2], pcache[3], | |
629 | p2c_header[0], p2c_header[1], p2c_header[2], p2c_header[3]); | |
630 | ||
631 | if (ops & PSP_MEM_TRAIN_SEND_SHORT_MSG) { | |
632 | DRM_DEBUG("Short training depends on restore.\n"); | |
633 | ops |= PSP_MEM_TRAIN_RESTORE; | |
634 | } | |
635 | ||
636 | if ((ops & PSP_MEM_TRAIN_RESTORE) && | |
637 | pcache[0] != MEM_TRAIN_SYSTEM_SIGNATURE) { | |
638 | DRM_DEBUG("sys_cache[0] is invalid, restore depends on save.\n"); | |
639 | ops |= PSP_MEM_TRAIN_SAVE; | |
640 | } | |
641 | ||
642 | if (p2c_header[0] == MEM_TRAIN_SYSTEM_SIGNATURE && | |
643 | !(pcache[0] == MEM_TRAIN_SYSTEM_SIGNATURE && | |
644 | pcache[3] == p2c_header[3])) { | |
645 | DRM_DEBUG("sys_cache is invalid or out-of-date, need save training data to sys_cache.\n"); | |
646 | ops |= PSP_MEM_TRAIN_SAVE; | |
647 | } | |
648 | ||
649 | if ((ops & PSP_MEM_TRAIN_SAVE) && | |
650 | p2c_header[0] != MEM_TRAIN_SYSTEM_SIGNATURE) { | |
651 | DRM_DEBUG("p2c_header[0] is invalid, save depends on long training.\n"); | |
652 | ops |= PSP_MEM_TRAIN_SEND_LONG_MSG; | |
653 | } | |
654 | ||
655 | if (ops & PSP_MEM_TRAIN_SEND_LONG_MSG) { | |
656 | ops &= ~PSP_MEM_TRAIN_SEND_SHORT_MSG; | |
657 | ops |= PSP_MEM_TRAIN_SAVE; | |
658 | } | |
659 | ||
660 | DRM_DEBUG("Memory training ops:%x.\n", ops); | |
661 | ||
662 | if (ops & PSP_MEM_TRAIN_SEND_LONG_MSG) { | |
240c811c | 663 | /* |
7c4f2b23 BC |
664 | * Long training will encroach a certain amount on the bottom of VRAM; |
665 | * save the content from the bottom of VRAM to system memory | |
666 | * before training, and restore it after training to avoid | |
240c811c TY |
667 | * VRAM corruption. |
668 | */ | |
669 | sz = GDDR6_MEM_TRAINING_ENCROACHED_SIZE; | |
670 | ||
671 | if (adev->gmc.visible_vram_size < sz || !adev->mman.aper_base_kaddr) { | |
672 | DRM_ERROR("visible_vram_size %llx or aper_base_kaddr %p is not initialized.\n", | |
673 | adev->gmc.visible_vram_size, | |
674 | adev->mman.aper_base_kaddr); | |
675 | return -EINVAL; | |
676 | } | |
677 | ||
678 | buf = vmalloc(sz); | |
679 | if (!buf) { | |
680 | DRM_ERROR("failed to allocate system memory.\n"); | |
681 | return -ENOMEM; | |
682 | } | |
683 | ||
684 | memcpy_fromio(buf, adev->mman.aper_base_kaddr, sz); | |
367039bf TY |
685 | ret = psp_v11_0_memory_training_send_msg(psp, PSP_BL__DRAM_LONG_TRAIN); |
686 | if (ret) { | |
687 | DRM_ERROR("Send long training msg failed.\n"); | |
240c811c | 688 | vfree(buf); |
367039bf TY |
689 | return ret; |
690 | } | |
240c811c TY |
691 | |
692 | memcpy_toio(adev->mman.aper_base_kaddr, buf, sz); | |
bf087285 | 693 | adev->hdp.funcs->flush_hdp(adev, NULL); |
240c811c | 694 | vfree(buf); |
367039bf TY |
695 | } |
696 | ||
697 | if (ops & PSP_MEM_TRAIN_SAVE) { | |
698 | amdgpu_device_vram_access(psp->adev, ctx->p2c_train_data_offset, ctx->sys_cache, ctx->train_data_size, false); | |
699 | } | |
700 | ||
701 | if (ops & PSP_MEM_TRAIN_RESTORE) { | |
702 | amdgpu_device_vram_access(psp->adev, ctx->c2p_train_data_offset, ctx->sys_cache, ctx->train_data_size, true); | |
703 | } | |
704 | ||
705 | if (ops & PSP_MEM_TRAIN_SEND_SHORT_MSG) { | |
706 | ret = psp_v11_0_memory_training_send_msg(psp, (amdgpu_force_long_training > 0) ? | |
707 | PSP_BL__DRAM_LONG_TRAIN : PSP_BL__DRAM_SHORT_TRAIN); | |
708 | if (ret) { | |
709 | DRM_ERROR("send training msg failed.\n"); | |
710 | return ret; | |
711 | } | |
712 | } | |
713 | ctx->training_cnt++; | |
714 | return 0; | |
715 | } | |
716 | ||
13a390a6 HZ |
717 | static uint32_t psp_v11_0_ring_get_wptr(struct psp_context *psp) |
718 | { | |
719 | uint32_t data; | |
720 | struct amdgpu_device *adev = psp->adev; | |
721 | ||
a2676149 | 722 | if (amdgpu_sriov_vf(adev)) |
13a390a6 HZ |
723 | data = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_102); |
724 | else | |
725 | data = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_67); | |
726 | ||
727 | return data; | |
728 | } | |
729 | ||
730 | static void psp_v11_0_ring_set_wptr(struct psp_context *psp, uint32_t value) | |
731 | { | |
732 | struct amdgpu_device *adev = psp->adev; | |
733 | ||
a2676149 | 734 | if (amdgpu_sriov_vf(adev)) { |
13a390a6 HZ |
735 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_102, value); |
736 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_101, GFX_CTRL_CMD_ID_CONSUME_CMD); | |
737 | } else | |
738 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_67, value); | |
739 | } | |
740 | ||
0dc93fd1 AG |
741 | static int psp_v11_0_load_usbc_pd_fw(struct psp_context *psp, dma_addr_t dma_addr) |
742 | { | |
743 | struct amdgpu_device *adev = psp->adev; | |
744 | uint32_t reg_status; | |
745 | int ret, i = 0; | |
746 | ||
747 | /* Write lower 32-bit address of the PD Controller FW */ | |
748 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36, lower_32_bits(dma_addr)); | |
749 | ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_35), | |
750 | 0x80000000, 0x80000000, false); | |
751 | if (ret) | |
752 | return ret; | |
753 | ||
754 | /* Fireup interrupt so PSP can pick up the lower address */ | |
755 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_35, 0x800000); | |
756 | ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_35), | |
757 | 0x80000000, 0x80000000, false); | |
758 | if (ret) | |
759 | return ret; | |
760 | ||
761 | reg_status = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_35); | |
762 | ||
763 | if ((reg_status & 0xFFFF) != 0) { | |
764 | DRM_ERROR("Lower address load failed - MP0_SMN_C2PMSG_35.Bits [15:0] = %02x...\n", | |
765 | reg_status & 0xFFFF); | |
766 | return -EIO; | |
767 | } | |
768 | ||
769 | /* Write upper 32-bit address of the PD Controller FW */ | |
770 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36, upper_32_bits(dma_addr)); | |
771 | ||
772 | ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_35), | |
773 | 0x80000000, 0x80000000, false); | |
774 | if (ret) | |
775 | return ret; | |
776 | ||
777 | /* Fireup interrupt so PSP can pick up the upper address */ | |
778 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_35, 0x4000000); | |
779 | ||
780 | /* FW load takes very long time */ | |
781 | do { | |
782 | msleep(1000); | |
783 | reg_status = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_35); | |
784 | ||
785 | if (reg_status & 0x80000000) | |
786 | goto done; | |
787 | ||
788 | } while (++i < USBC_PD_POLLING_LIMIT_S); | |
789 | ||
790 | return -ETIME; | |
791 | done: | |
792 | ||
793 | if ((reg_status & 0xFFFF) != 0) { | |
794 | DRM_ERROR("Upper address load failed - MP0_SMN_C2PMSG_35.Bits [15:0] = x%04x\n", | |
795 | reg_status & 0xFFFF); | |
796 | return -EIO; | |
797 | } | |
798 | ||
799 | return 0; | |
800 | } | |
801 | ||
802 | static int psp_v11_0_read_usbc_pd_fw(struct psp_context *psp, uint32_t *fw_ver) | |
803 | { | |
804 | struct amdgpu_device *adev = psp->adev; | |
805 | int ret; | |
806 | ||
807 | WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_35, C2PMSG_CMD_GFX_USB_PD_FW_VER); | |
808 | ||
809 | ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_35), | |
810 | 0x80000000, 0x80000000, false); | |
811 | if (!ret) | |
812 | *fw_ver = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_36); | |
813 | ||
814 | return ret; | |
815 | } | |
816 | ||
654f761c FX |
817 | static const struct psp_funcs psp_v11_0_funcs = { |
818 | .init_microcode = psp_v11_0_init_microcode, | |
42989359 | 819 | .bootloader_load_kdb = psp_v11_0_bootloader_load_kdb, |
70509057 | 820 | .bootloader_load_spl = psp_v11_0_bootloader_load_spl, |
654f761c FX |
821 | .bootloader_load_sysdrv = psp_v11_0_bootloader_load_sysdrv, |
822 | .bootloader_load_sos = psp_v11_0_bootloader_load_sos, | |
654f761c FX |
823 | .ring_init = psp_v11_0_ring_init, |
824 | .ring_create = psp_v11_0_ring_create, | |
825 | .ring_stop = psp_v11_0_ring_stop, | |
826 | .ring_destroy = psp_v11_0_ring_destroy, | |
654f761c | 827 | .mode1_reset = psp_v11_0_mode1_reset, |
367039bf | 828 | .mem_training = psp_v11_0_memory_training, |
13a390a6 HZ |
829 | .ring_get_wptr = psp_v11_0_ring_get_wptr, |
830 | .ring_set_wptr = psp_v11_0_ring_set_wptr, | |
0dc93fd1 AG |
831 | .load_usbc_pd_fw = psp_v11_0_load_usbc_pd_fw, |
832 | .read_usbc_pd_fw = psp_v11_0_read_usbc_pd_fw | |
654f761c FX |
833 | }; |
834 | ||
835 | void psp_v11_0_set_psp_funcs(struct psp_context *psp) | |
836 | { | |
837 | psp->funcs = &psp_v11_0_funcs; | |
838 | } |