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