1b843c749SSergey Zigachev /* 2b843c749SSergey Zigachev * Copyright 2015 Advanced Micro Devices, Inc. 3b843c749SSergey Zigachev * 4b843c749SSergey Zigachev * Permission is hereby granted, free of charge, to any person obtaining a 5b843c749SSergey Zigachev * copy of this software and associated documentation files (the "Software"), 6b843c749SSergey Zigachev * to deal in the Software without restriction, including without limitation 7b843c749SSergey Zigachev * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8b843c749SSergey Zigachev * and/or sell copies of the Software, and to permit persons to whom the 9b843c749SSergey Zigachev * Software is furnished to do so, subject to the following conditions: 10b843c749SSergey Zigachev * 11b843c749SSergey Zigachev * The above copyright notice and this permission notice shall be included in 12b843c749SSergey Zigachev * all copies or substantial portions of the Software. 13b843c749SSergey Zigachev * 14b843c749SSergey Zigachev * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15b843c749SSergey Zigachev * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16b843c749SSergey Zigachev * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17b843c749SSergey Zigachev * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18b843c749SSergey Zigachev * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19b843c749SSergey Zigachev * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20b843c749SSergey Zigachev * OTHER DEALINGS IN THE SOFTWARE. 21b843c749SSergey Zigachev * 22b843c749SSergey Zigachev * 23b843c749SSergey Zigachev */ 24b843c749SSergey Zigachev #include <linux/list.h> 25b843c749SSergey Zigachev #include <linux/slab.h> 26b843c749SSergey Zigachev #include <drm/drmP.h> 27b843c749SSergey Zigachev #include <linux/firmware.h> 28b843c749SSergey Zigachev #include <drm/amdgpu_drm.h> 29b843c749SSergey Zigachev #include "amdgpu.h" 30b843c749SSergey Zigachev #include "atom.h" 31b843c749SSergey Zigachev #include "amdgpu_ucode.h" 32b843c749SSergey Zigachev 33b843c749SSergey Zigachev struct amdgpu_cgs_device { 34b843c749SSergey Zigachev struct cgs_device base; 35b843c749SSergey Zigachev struct amdgpu_device *adev; 36b843c749SSergey Zigachev }; 37b843c749SSergey Zigachev 38b843c749SSergey Zigachev #define CGS_FUNC_ADEV \ 39b843c749SSergey Zigachev struct amdgpu_device *adev = \ 40b843c749SSergey Zigachev ((struct amdgpu_cgs_device *)cgs_device)->adev 41b843c749SSergey Zigachev 42b843c749SSergey Zigachev 43b843c749SSergey Zigachev static uint32_t amdgpu_cgs_read_register(struct cgs_device *cgs_device, unsigned offset) 44b843c749SSergey Zigachev { 45b843c749SSergey Zigachev CGS_FUNC_ADEV; 46b843c749SSergey Zigachev return RREG32(offset); 47b843c749SSergey Zigachev } 48b843c749SSergey Zigachev 49b843c749SSergey Zigachev static void amdgpu_cgs_write_register(struct cgs_device *cgs_device, unsigned offset, 50b843c749SSergey Zigachev uint32_t value) 51b843c749SSergey Zigachev { 52b843c749SSergey Zigachev CGS_FUNC_ADEV; 53b843c749SSergey Zigachev WREG32(offset, value); 54b843c749SSergey Zigachev } 55b843c749SSergey Zigachev 56b843c749SSergey Zigachev static uint32_t amdgpu_cgs_read_ind_register(struct cgs_device *cgs_device, 57b843c749SSergey Zigachev enum cgs_ind_reg space, 58b843c749SSergey Zigachev unsigned index) 59b843c749SSergey Zigachev { 60b843c749SSergey Zigachev CGS_FUNC_ADEV; 61b843c749SSergey Zigachev switch (space) { 62b843c749SSergey Zigachev case CGS_IND_REG__MMIO: 63b843c749SSergey Zigachev return RREG32_IDX(index); 64b843c749SSergey Zigachev case CGS_IND_REG__PCIE: 65b843c749SSergey Zigachev return RREG32_PCIE(index); 66b843c749SSergey Zigachev case CGS_IND_REG__SMC: 67b843c749SSergey Zigachev return RREG32_SMC(index); 68b843c749SSergey Zigachev case CGS_IND_REG__UVD_CTX: 69b843c749SSergey Zigachev return RREG32_UVD_CTX(index); 70b843c749SSergey Zigachev case CGS_IND_REG__DIDT: 71b843c749SSergey Zigachev return RREG32_DIDT(index); 72b843c749SSergey Zigachev case CGS_IND_REG_GC_CAC: 73b843c749SSergey Zigachev return RREG32_GC_CAC(index); 74b843c749SSergey Zigachev case CGS_IND_REG_SE_CAC: 75b843c749SSergey Zigachev return RREG32_SE_CAC(index); 76b843c749SSergey Zigachev case CGS_IND_REG__AUDIO_ENDPT: 77b843c749SSergey Zigachev DRM_ERROR("audio endpt register access not implemented.\n"); 78b843c749SSergey Zigachev return 0; 79b843c749SSergey Zigachev } 80b843c749SSergey Zigachev WARN(1, "Invalid indirect register space"); 81b843c749SSergey Zigachev return 0; 82b843c749SSergey Zigachev } 83b843c749SSergey Zigachev 84b843c749SSergey Zigachev static void amdgpu_cgs_write_ind_register(struct cgs_device *cgs_device, 85b843c749SSergey Zigachev enum cgs_ind_reg space, 86b843c749SSergey Zigachev unsigned index, uint32_t value) 87b843c749SSergey Zigachev { 88b843c749SSergey Zigachev CGS_FUNC_ADEV; 89b843c749SSergey Zigachev switch (space) { 90b843c749SSergey Zigachev case CGS_IND_REG__MMIO: 91b843c749SSergey Zigachev return WREG32_IDX(index, value); 92b843c749SSergey Zigachev case CGS_IND_REG__PCIE: 93b843c749SSergey Zigachev return WREG32_PCIE(index, value); 94b843c749SSergey Zigachev case CGS_IND_REG__SMC: 95b843c749SSergey Zigachev return WREG32_SMC(index, value); 96b843c749SSergey Zigachev case CGS_IND_REG__UVD_CTX: 97b843c749SSergey Zigachev return WREG32_UVD_CTX(index, value); 98b843c749SSergey Zigachev case CGS_IND_REG__DIDT: 99b843c749SSergey Zigachev return WREG32_DIDT(index, value); 100b843c749SSergey Zigachev case CGS_IND_REG_GC_CAC: 101b843c749SSergey Zigachev return WREG32_GC_CAC(index, value); 102b843c749SSergey Zigachev case CGS_IND_REG_SE_CAC: 103b843c749SSergey Zigachev return WREG32_SE_CAC(index, value); 104b843c749SSergey Zigachev case CGS_IND_REG__AUDIO_ENDPT: 105b843c749SSergey Zigachev DRM_ERROR("audio endpt register access not implemented.\n"); 106b843c749SSergey Zigachev return; 107b843c749SSergey Zigachev } 108b843c749SSergey Zigachev WARN(1, "Invalid indirect register space"); 109b843c749SSergey Zigachev } 110b843c749SSergey Zigachev 111b843c749SSergey Zigachev static uint32_t fw_type_convert(struct cgs_device *cgs_device, uint32_t fw_type) 112b843c749SSergey Zigachev { 113b843c749SSergey Zigachev CGS_FUNC_ADEV; 114b843c749SSergey Zigachev enum AMDGPU_UCODE_ID result = AMDGPU_UCODE_ID_MAXIMUM; 115b843c749SSergey Zigachev 116b843c749SSergey Zigachev switch (fw_type) { 117b843c749SSergey Zigachev case CGS_UCODE_ID_SDMA0: 118b843c749SSergey Zigachev result = AMDGPU_UCODE_ID_SDMA0; 119b843c749SSergey Zigachev break; 120b843c749SSergey Zigachev case CGS_UCODE_ID_SDMA1: 121b843c749SSergey Zigachev result = AMDGPU_UCODE_ID_SDMA1; 122b843c749SSergey Zigachev break; 123b843c749SSergey Zigachev case CGS_UCODE_ID_CP_CE: 124b843c749SSergey Zigachev result = AMDGPU_UCODE_ID_CP_CE; 125b843c749SSergey Zigachev break; 126b843c749SSergey Zigachev case CGS_UCODE_ID_CP_PFP: 127b843c749SSergey Zigachev result = AMDGPU_UCODE_ID_CP_PFP; 128b843c749SSergey Zigachev break; 129b843c749SSergey Zigachev case CGS_UCODE_ID_CP_ME: 130b843c749SSergey Zigachev result = AMDGPU_UCODE_ID_CP_ME; 131b843c749SSergey Zigachev break; 132b843c749SSergey Zigachev case CGS_UCODE_ID_CP_MEC: 133b843c749SSergey Zigachev case CGS_UCODE_ID_CP_MEC_JT1: 134b843c749SSergey Zigachev result = AMDGPU_UCODE_ID_CP_MEC1; 135b843c749SSergey Zigachev break; 136b843c749SSergey Zigachev case CGS_UCODE_ID_CP_MEC_JT2: 137b843c749SSergey Zigachev /* for VI. JT2 should be the same as JT1, because: 138b843c749SSergey Zigachev 1, MEC2 and MEC1 use exactly same FW. 139b843c749SSergey Zigachev 2, JT2 is not pached but JT1 is. 140b843c749SSergey Zigachev */ 141b843c749SSergey Zigachev if (adev->asic_type >= CHIP_TOPAZ) 142b843c749SSergey Zigachev result = AMDGPU_UCODE_ID_CP_MEC1; 143b843c749SSergey Zigachev else 144b843c749SSergey Zigachev result = AMDGPU_UCODE_ID_CP_MEC2; 145b843c749SSergey Zigachev break; 146b843c749SSergey Zigachev case CGS_UCODE_ID_RLC_G: 147b843c749SSergey Zigachev result = AMDGPU_UCODE_ID_RLC_G; 148b843c749SSergey Zigachev break; 149b843c749SSergey Zigachev case CGS_UCODE_ID_STORAGE: 150b843c749SSergey Zigachev result = AMDGPU_UCODE_ID_STORAGE; 151b843c749SSergey Zigachev break; 152b843c749SSergey Zigachev default: 153b843c749SSergey Zigachev DRM_ERROR("Firmware type not supported\n"); 154b843c749SSergey Zigachev } 155b843c749SSergey Zigachev return result; 156b843c749SSergey Zigachev } 157b843c749SSergey Zigachev 158b843c749SSergey Zigachev static uint16_t amdgpu_get_firmware_version(struct cgs_device *cgs_device, 159b843c749SSergey Zigachev enum cgs_ucode_id type) 160b843c749SSergey Zigachev { 161b843c749SSergey Zigachev CGS_FUNC_ADEV; 162b843c749SSergey Zigachev uint16_t fw_version = 0; 163b843c749SSergey Zigachev 164b843c749SSergey Zigachev switch (type) { 165b843c749SSergey Zigachev case CGS_UCODE_ID_SDMA0: 166b843c749SSergey Zigachev fw_version = adev->sdma.instance[0].fw_version; 167b843c749SSergey Zigachev break; 168b843c749SSergey Zigachev case CGS_UCODE_ID_SDMA1: 169b843c749SSergey Zigachev fw_version = adev->sdma.instance[1].fw_version; 170b843c749SSergey Zigachev break; 171b843c749SSergey Zigachev case CGS_UCODE_ID_CP_CE: 172b843c749SSergey Zigachev fw_version = adev->gfx.ce_fw_version; 173b843c749SSergey Zigachev break; 174b843c749SSergey Zigachev case CGS_UCODE_ID_CP_PFP: 175b843c749SSergey Zigachev fw_version = adev->gfx.pfp_fw_version; 176b843c749SSergey Zigachev break; 177b843c749SSergey Zigachev case CGS_UCODE_ID_CP_ME: 178b843c749SSergey Zigachev fw_version = adev->gfx.me_fw_version; 179b843c749SSergey Zigachev break; 180b843c749SSergey Zigachev case CGS_UCODE_ID_CP_MEC: 181b843c749SSergey Zigachev fw_version = adev->gfx.mec_fw_version; 182b843c749SSergey Zigachev break; 183b843c749SSergey Zigachev case CGS_UCODE_ID_CP_MEC_JT1: 184b843c749SSergey Zigachev fw_version = adev->gfx.mec_fw_version; 185b843c749SSergey Zigachev break; 186b843c749SSergey Zigachev case CGS_UCODE_ID_CP_MEC_JT2: 187b843c749SSergey Zigachev fw_version = adev->gfx.mec_fw_version; 188b843c749SSergey Zigachev break; 189b843c749SSergey Zigachev case CGS_UCODE_ID_RLC_G: 190b843c749SSergey Zigachev fw_version = adev->gfx.rlc_fw_version; 191b843c749SSergey Zigachev break; 192b843c749SSergey Zigachev case CGS_UCODE_ID_STORAGE: 193b843c749SSergey Zigachev break; 194b843c749SSergey Zigachev default: 195b843c749SSergey Zigachev DRM_ERROR("firmware type %d do not have version\n", type); 196b843c749SSergey Zigachev break; 197b843c749SSergey Zigachev } 198b843c749SSergey Zigachev return fw_version; 199b843c749SSergey Zigachev } 200b843c749SSergey Zigachev 201b843c749SSergey Zigachev static int amdgpu_cgs_get_firmware_info(struct cgs_device *cgs_device, 202b843c749SSergey Zigachev enum cgs_ucode_id type, 203b843c749SSergey Zigachev struct cgs_firmware_info *info) 204b843c749SSergey Zigachev { 205b843c749SSergey Zigachev CGS_FUNC_ADEV; 206b843c749SSergey Zigachev 207b843c749SSergey Zigachev if ((CGS_UCODE_ID_SMU != type) && (CGS_UCODE_ID_SMU_SK != type)) { 208b843c749SSergey Zigachev uint64_t gpu_addr; 209b843c749SSergey Zigachev uint32_t data_size; 210b843c749SSergey Zigachev const struct gfx_firmware_header_v1_0 *header; 211b843c749SSergey Zigachev enum AMDGPU_UCODE_ID id; 212b843c749SSergey Zigachev struct amdgpu_firmware_info *ucode; 213b843c749SSergey Zigachev 214b843c749SSergey Zigachev id = fw_type_convert(cgs_device, type); 215b843c749SSergey Zigachev ucode = &adev->firmware.ucode[id]; 216b843c749SSergey Zigachev if (ucode->fw == NULL) 217b843c749SSergey Zigachev return -EINVAL; 218b843c749SSergey Zigachev 219b843c749SSergey Zigachev gpu_addr = ucode->mc_addr; 220b843c749SSergey Zigachev header = (const struct gfx_firmware_header_v1_0 *)ucode->fw->data; 221b843c749SSergey Zigachev data_size = le32_to_cpu(header->header.ucode_size_bytes); 222b843c749SSergey Zigachev 223b843c749SSergey Zigachev if ((type == CGS_UCODE_ID_CP_MEC_JT1) || 224b843c749SSergey Zigachev (type == CGS_UCODE_ID_CP_MEC_JT2)) { 225b843c749SSergey Zigachev gpu_addr += ALIGN(le32_to_cpu(header->header.ucode_size_bytes), PAGE_SIZE); 226b843c749SSergey Zigachev data_size = le32_to_cpu(header->jt_size) << 2; 227b843c749SSergey Zigachev } 228b843c749SSergey Zigachev 229b843c749SSergey Zigachev info->kptr = ucode->kaddr; 230b843c749SSergey Zigachev info->image_size = data_size; 231b843c749SSergey Zigachev info->mc_addr = gpu_addr; 232b843c749SSergey Zigachev info->version = (uint16_t)le32_to_cpu(header->header.ucode_version); 233b843c749SSergey Zigachev 234b843c749SSergey Zigachev if (CGS_UCODE_ID_CP_MEC == type) 235b843c749SSergey Zigachev info->image_size = le32_to_cpu(header->jt_offset) << 2; 236b843c749SSergey Zigachev 237b843c749SSergey Zigachev info->fw_version = amdgpu_get_firmware_version(cgs_device, type); 238b843c749SSergey Zigachev info->feature_version = (uint16_t)le32_to_cpu(header->ucode_feature_version); 239b843c749SSergey Zigachev } else { 240b843c749SSergey Zigachev char fw_name[30] = {0}; 241b843c749SSergey Zigachev int err = 0; 242b843c749SSergey Zigachev uint32_t ucode_size; 243b843c749SSergey Zigachev uint32_t ucode_start_address; 244b843c749SSergey Zigachev const uint8_t *src; 245b843c749SSergey Zigachev const struct smc_firmware_header_v1_0 *hdr; 246b843c749SSergey Zigachev const struct common_firmware_header *header; 247b843c749SSergey Zigachev struct amdgpu_firmware_info *ucode = NULL; 248b843c749SSergey Zigachev 249b843c749SSergey Zigachev if (!adev->pm.fw) { 250b843c749SSergey Zigachev switch (adev->asic_type) { 251b843c749SSergey Zigachev case CHIP_TAHITI: 252b843c749SSergey Zigachev strcpy(fw_name, "radeon/tahiti_smc.bin"); 253b843c749SSergey Zigachev break; 254b843c749SSergey Zigachev case CHIP_PITCAIRN: 255b843c749SSergey Zigachev if ((adev->pdev->revision == 0x81) && 256b843c749SSergey Zigachev ((adev->pdev->device == 0x6810) || 257b843c749SSergey Zigachev (adev->pdev->device == 0x6811))) { 258b843c749SSergey Zigachev info->is_kicker = true; 259b843c749SSergey Zigachev strcpy(fw_name, "radeon/pitcairn_k_smc.bin"); 260b843c749SSergey Zigachev } else { 261b843c749SSergey Zigachev strcpy(fw_name, "radeon/pitcairn_smc.bin"); 262b843c749SSergey Zigachev } 263b843c749SSergey Zigachev break; 264b843c749SSergey Zigachev case CHIP_VERDE: 265b843c749SSergey Zigachev if (((adev->pdev->device == 0x6820) && 266b843c749SSergey Zigachev ((adev->pdev->revision == 0x81) || 267b843c749SSergey Zigachev (adev->pdev->revision == 0x83))) || 268b843c749SSergey Zigachev ((adev->pdev->device == 0x6821) && 269b843c749SSergey Zigachev ((adev->pdev->revision == 0x83) || 270b843c749SSergey Zigachev (adev->pdev->revision == 0x87))) || 271b843c749SSergey Zigachev ((adev->pdev->revision == 0x87) && 272b843c749SSergey Zigachev ((adev->pdev->device == 0x6823) || 273b843c749SSergey Zigachev (adev->pdev->device == 0x682b)))) { 274b843c749SSergey Zigachev info->is_kicker = true; 275b843c749SSergey Zigachev strcpy(fw_name, "radeon/verde_k_smc.bin"); 276b843c749SSergey Zigachev } else { 277b843c749SSergey Zigachev strcpy(fw_name, "radeon/verde_smc.bin"); 278b843c749SSergey Zigachev } 279b843c749SSergey Zigachev break; 280b843c749SSergey Zigachev case CHIP_OLAND: 281b843c749SSergey Zigachev if (((adev->pdev->revision == 0x81) && 282b843c749SSergey Zigachev ((adev->pdev->device == 0x6600) || 283b843c749SSergey Zigachev (adev->pdev->device == 0x6604) || 284b843c749SSergey Zigachev (adev->pdev->device == 0x6605) || 285b843c749SSergey Zigachev (adev->pdev->device == 0x6610))) || 286b843c749SSergey Zigachev ((adev->pdev->revision == 0x83) && 287b843c749SSergey Zigachev (adev->pdev->device == 0x6610))) { 288b843c749SSergey Zigachev info->is_kicker = true; 289b843c749SSergey Zigachev strcpy(fw_name, "radeon/oland_k_smc.bin"); 290b843c749SSergey Zigachev } else { 291b843c749SSergey Zigachev strcpy(fw_name, "radeon/oland_smc.bin"); 292b843c749SSergey Zigachev } 293b843c749SSergey Zigachev break; 294b843c749SSergey Zigachev case CHIP_HAINAN: 295b843c749SSergey Zigachev if (((adev->pdev->revision == 0x81) && 296b843c749SSergey Zigachev (adev->pdev->device == 0x6660)) || 297b843c749SSergey Zigachev ((adev->pdev->revision == 0x83) && 298b843c749SSergey Zigachev ((adev->pdev->device == 0x6660) || 299b843c749SSergey Zigachev (adev->pdev->device == 0x6663) || 300b843c749SSergey Zigachev (adev->pdev->device == 0x6665) || 301b843c749SSergey Zigachev (adev->pdev->device == 0x6667)))) { 302b843c749SSergey Zigachev info->is_kicker = true; 303b843c749SSergey Zigachev strcpy(fw_name, "radeon/hainan_k_smc.bin"); 304b843c749SSergey Zigachev } else if ((adev->pdev->revision == 0xc3) && 305b843c749SSergey Zigachev (adev->pdev->device == 0x6665)) { 306b843c749SSergey Zigachev info->is_kicker = true; 307b843c749SSergey Zigachev strcpy(fw_name, "radeon/banks_k_2_smc.bin"); 308b843c749SSergey Zigachev } else { 309b843c749SSergey Zigachev strcpy(fw_name, "radeon/hainan_smc.bin"); 310b843c749SSergey Zigachev } 311b843c749SSergey Zigachev break; 312b843c749SSergey Zigachev case CHIP_BONAIRE: 313b843c749SSergey Zigachev if ((adev->pdev->revision == 0x80) || 314b843c749SSergey Zigachev (adev->pdev->revision == 0x81) || 315b843c749SSergey Zigachev (adev->pdev->device == 0x665f)) { 316b843c749SSergey Zigachev info->is_kicker = true; 317b843c749SSergey Zigachev strcpy(fw_name, "amdgpu/bonaire_k_smc.bin"); 318b843c749SSergey Zigachev } else { 319b843c749SSergey Zigachev strcpy(fw_name, "amdgpu/bonaire_smc.bin"); 320b843c749SSergey Zigachev } 321b843c749SSergey Zigachev break; 322b843c749SSergey Zigachev case CHIP_HAWAII: 323b843c749SSergey Zigachev if (adev->pdev->revision == 0x80) { 324b843c749SSergey Zigachev info->is_kicker = true; 325b843c749SSergey Zigachev strcpy(fw_name, "amdgpu/hawaii_k_smc.bin"); 326b843c749SSergey Zigachev } else { 327b843c749SSergey Zigachev strcpy(fw_name, "amdgpu/hawaii_smc.bin"); 328b843c749SSergey Zigachev } 329b843c749SSergey Zigachev break; 330b843c749SSergey Zigachev case CHIP_TOPAZ: 331b843c749SSergey Zigachev if (((adev->pdev->device == 0x6900) && (adev->pdev->revision == 0x81)) || 332b843c749SSergey Zigachev ((adev->pdev->device == 0x6900) && (adev->pdev->revision == 0x83)) || 333b843c749SSergey Zigachev ((adev->pdev->device == 0x6907) && (adev->pdev->revision == 0x87)) || 334b843c749SSergey Zigachev ((adev->pdev->device == 0x6900) && (adev->pdev->revision == 0xD1)) || 335b843c749SSergey Zigachev ((adev->pdev->device == 0x6900) && (adev->pdev->revision == 0xD3))) { 336b843c749SSergey Zigachev info->is_kicker = true; 337b843c749SSergey Zigachev strcpy(fw_name, "amdgpu/topaz_k_smc.bin"); 338b843c749SSergey Zigachev } else 339b843c749SSergey Zigachev strcpy(fw_name, "amdgpu/topaz_smc.bin"); 340b843c749SSergey Zigachev break; 341b843c749SSergey Zigachev case CHIP_TONGA: 342b843c749SSergey Zigachev if (((adev->pdev->device == 0x6939) && (adev->pdev->revision == 0xf1)) || 343b843c749SSergey Zigachev ((adev->pdev->device == 0x6938) && (adev->pdev->revision == 0xf1))) { 344b843c749SSergey Zigachev info->is_kicker = true; 345b843c749SSergey Zigachev strcpy(fw_name, "amdgpu/tonga_k_smc.bin"); 346b843c749SSergey Zigachev } else 347b843c749SSergey Zigachev strcpy(fw_name, "amdgpu/tonga_smc.bin"); 348b843c749SSergey Zigachev break; 349b843c749SSergey Zigachev case CHIP_FIJI: 350b843c749SSergey Zigachev strcpy(fw_name, "amdgpu/fiji_smc.bin"); 351b843c749SSergey Zigachev break; 352b843c749SSergey Zigachev case CHIP_POLARIS11: 353b843c749SSergey Zigachev if (type == CGS_UCODE_ID_SMU) { 354b843c749SSergey Zigachev if (((adev->pdev->device == 0x67ef) && 355b843c749SSergey Zigachev ((adev->pdev->revision == 0xe0) || 356b843c749SSergey Zigachev (adev->pdev->revision == 0xe5))) || 357b843c749SSergey Zigachev ((adev->pdev->device == 0x67ff) && 358b843c749SSergey Zigachev ((adev->pdev->revision == 0xcf) || 359b843c749SSergey Zigachev (adev->pdev->revision == 0xef) || 360b843c749SSergey Zigachev (adev->pdev->revision == 0xff)))) { 361b843c749SSergey Zigachev info->is_kicker = true; 362b843c749SSergey Zigachev strcpy(fw_name, "amdgpu/polaris11_k_smc.bin"); 363b843c749SSergey Zigachev } else if ((adev->pdev->device == 0x67ef) && 364b843c749SSergey Zigachev (adev->pdev->revision == 0xe2)) { 365b843c749SSergey Zigachev info->is_kicker = true; 366b843c749SSergey Zigachev strcpy(fw_name, "amdgpu/polaris11_k2_smc.bin"); 367b843c749SSergey Zigachev } else { 368b843c749SSergey Zigachev strcpy(fw_name, "amdgpu/polaris11_smc.bin"); 369b843c749SSergey Zigachev } 370b843c749SSergey Zigachev } else if (type == CGS_UCODE_ID_SMU_SK) { 371b843c749SSergey Zigachev strcpy(fw_name, "amdgpu/polaris11_smc_sk.bin"); 372b843c749SSergey Zigachev } 373b843c749SSergey Zigachev break; 374b843c749SSergey Zigachev case CHIP_POLARIS10: 375b843c749SSergey Zigachev if (type == CGS_UCODE_ID_SMU) { 376b843c749SSergey Zigachev if (((adev->pdev->device == 0x67df) && 377b843c749SSergey Zigachev ((adev->pdev->revision == 0xe0) || 378b843c749SSergey Zigachev (adev->pdev->revision == 0xe3) || 379b843c749SSergey Zigachev (adev->pdev->revision == 0xe4) || 380b843c749SSergey Zigachev (adev->pdev->revision == 0xe5) || 381b843c749SSergey Zigachev (adev->pdev->revision == 0xe7) || 382b843c749SSergey Zigachev (adev->pdev->revision == 0xef))) || 383b843c749SSergey Zigachev ((adev->pdev->device == 0x6fdf) && 384b843c749SSergey Zigachev ((adev->pdev->revision == 0xef) || 385b843c749SSergey Zigachev (adev->pdev->revision == 0xff)))) { 386b843c749SSergey Zigachev info->is_kicker = true; 387b843c749SSergey Zigachev strcpy(fw_name, "amdgpu/polaris10_k_smc.bin"); 388b843c749SSergey Zigachev } else if ((adev->pdev->device == 0x67df) && 389b843c749SSergey Zigachev ((adev->pdev->revision == 0xe1) || 390b843c749SSergey Zigachev (adev->pdev->revision == 0xf7))) { 391b843c749SSergey Zigachev info->is_kicker = true; 392b843c749SSergey Zigachev strcpy(fw_name, "amdgpu/polaris10_k2_smc.bin"); 393b843c749SSergey Zigachev } else { 394b843c749SSergey Zigachev strcpy(fw_name, "amdgpu/polaris10_smc.bin"); 395b843c749SSergey Zigachev } 396b843c749SSergey Zigachev } else if (type == CGS_UCODE_ID_SMU_SK) { 397b843c749SSergey Zigachev strcpy(fw_name, "amdgpu/polaris10_smc_sk.bin"); 398b843c749SSergey Zigachev } 399b843c749SSergey Zigachev break; 400b843c749SSergey Zigachev case CHIP_POLARIS12: 401b843c749SSergey Zigachev if (((adev->pdev->device == 0x6987) && 402b843c749SSergey Zigachev ((adev->pdev->revision == 0xc0) || 403b843c749SSergey Zigachev (adev->pdev->revision == 0xc3))) || 404b843c749SSergey Zigachev ((adev->pdev->device == 0x6981) && 405b843c749SSergey Zigachev ((adev->pdev->revision == 0x00) || 406b843c749SSergey Zigachev (adev->pdev->revision == 0x01) || 407b843c749SSergey Zigachev (adev->pdev->revision == 0x10)))) { 408b843c749SSergey Zigachev info->is_kicker = true; 409b843c749SSergey Zigachev strcpy(fw_name, "amdgpu/polaris12_k_smc.bin"); 410b843c749SSergey Zigachev } else { 411b843c749SSergey Zigachev strcpy(fw_name, "amdgpu/polaris12_smc.bin"); 412b843c749SSergey Zigachev } 413b843c749SSergey Zigachev break; 414b843c749SSergey Zigachev case CHIP_VEGAM: 415b843c749SSergey Zigachev strcpy(fw_name, "amdgpu/vegam_smc.bin"); 416b843c749SSergey Zigachev break; 417b843c749SSergey Zigachev case CHIP_VEGA10: 418b843c749SSergey Zigachev if ((adev->pdev->device == 0x687f) && 419b843c749SSergey Zigachev ((adev->pdev->revision == 0xc0) || 420b843c749SSergey Zigachev (adev->pdev->revision == 0xc1) || 421b843c749SSergey Zigachev (adev->pdev->revision == 0xc3))) 422b843c749SSergey Zigachev strcpy(fw_name, "amdgpu/vega10_acg_smc.bin"); 423b843c749SSergey Zigachev else 424b843c749SSergey Zigachev strcpy(fw_name, "amdgpu/vega10_smc.bin"); 425b843c749SSergey Zigachev break; 426b843c749SSergey Zigachev case CHIP_VEGA12: 427b843c749SSergey Zigachev strcpy(fw_name, "amdgpu/vega12_smc.bin"); 428b843c749SSergey Zigachev break; 429b843c749SSergey Zigachev case CHIP_VEGA20: 430b843c749SSergey Zigachev strcpy(fw_name, "amdgpu/vega20_smc.bin"); 431b843c749SSergey Zigachev break; 432b843c749SSergey Zigachev default: 433b843c749SSergey Zigachev DRM_ERROR("SMC firmware not supported\n"); 434b843c749SSergey Zigachev return -EINVAL; 435b843c749SSergey Zigachev } 436b843c749SSergey Zigachev 437b843c749SSergey Zigachev err = request_firmware(&adev->pm.fw, fw_name, adev->dev); 438b843c749SSergey Zigachev if (err) { 439b843c749SSergey Zigachev DRM_ERROR("Failed to request firmware\n"); 440b843c749SSergey Zigachev return err; 441b843c749SSergey Zigachev } 442b843c749SSergey Zigachev 443b843c749SSergey Zigachev err = amdgpu_ucode_validate(adev->pm.fw); 444b843c749SSergey Zigachev if (err) { 445b843c749SSergey Zigachev DRM_ERROR("Failed to load firmware \"%s\"", fw_name); 446b843c749SSergey Zigachev release_firmware(adev->pm.fw); 447b843c749SSergey Zigachev adev->pm.fw = NULL; 448b843c749SSergey Zigachev return err; 449b843c749SSergey Zigachev } 450b843c749SSergey Zigachev 451b843c749SSergey Zigachev if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) { 452b843c749SSergey Zigachev ucode = &adev->firmware.ucode[AMDGPU_UCODE_ID_SMC]; 453b843c749SSergey Zigachev ucode->ucode_id = AMDGPU_UCODE_ID_SMC; 454b843c749SSergey Zigachev ucode->fw = adev->pm.fw; 455b843c749SSergey Zigachev header = (const struct common_firmware_header *)ucode->fw->data; 456b843c749SSergey Zigachev adev->firmware.fw_size += 457b843c749SSergey Zigachev ALIGN(le32_to_cpu(header->ucode_size_bytes), PAGE_SIZE); 458b843c749SSergey Zigachev } 459b843c749SSergey Zigachev } 460b843c749SSergey Zigachev 461b843c749SSergey Zigachev hdr = (const struct smc_firmware_header_v1_0 *) adev->pm.fw->data; 462b843c749SSergey Zigachev amdgpu_ucode_print_smc_hdr(&hdr->header); 463b843c749SSergey Zigachev adev->pm.fw_version = le32_to_cpu(hdr->header.ucode_version); 464b843c749SSergey Zigachev ucode_size = le32_to_cpu(hdr->header.ucode_size_bytes); 465b843c749SSergey Zigachev ucode_start_address = le32_to_cpu(hdr->ucode_start_addr); 466b843c749SSergey Zigachev src = (const uint8_t *)(adev->pm.fw->data + 467b843c749SSergey Zigachev le32_to_cpu(hdr->header.ucode_array_offset_bytes)); 468b843c749SSergey Zigachev 469b843c749SSergey Zigachev info->version = adev->pm.fw_version; 470b843c749SSergey Zigachev info->image_size = ucode_size; 471b843c749SSergey Zigachev info->ucode_start_address = ucode_start_address; 472b843c749SSergey Zigachev info->kptr = (void *)src; 473b843c749SSergey Zigachev } 474b843c749SSergey Zigachev return 0; 475b843c749SSergey Zigachev } 476b843c749SSergey Zigachev 477b843c749SSergey Zigachev static const struct cgs_ops amdgpu_cgs_ops = { 478b843c749SSergey Zigachev .read_register = amdgpu_cgs_read_register, 479b843c749SSergey Zigachev .write_register = amdgpu_cgs_write_register, 480b843c749SSergey Zigachev .read_ind_register = amdgpu_cgs_read_ind_register, 481b843c749SSergey Zigachev .write_ind_register = amdgpu_cgs_write_ind_register, 482b843c749SSergey Zigachev .get_firmware_info = amdgpu_cgs_get_firmware_info, 483b843c749SSergey Zigachev }; 484b843c749SSergey Zigachev 485b843c749SSergey Zigachev struct cgs_device *amdgpu_cgs_create_device(struct amdgpu_device *adev) 486b843c749SSergey Zigachev { 487b843c749SSergey Zigachev struct amdgpu_cgs_device *cgs_device = 488*78973132SSergey Zigachev kmalloc(sizeof(*cgs_device), M_DRM, GFP_KERNEL); 489b843c749SSergey Zigachev 490b843c749SSergey Zigachev if (!cgs_device) { 491b843c749SSergey Zigachev DRM_ERROR("Couldn't allocate CGS device structure\n"); 492b843c749SSergey Zigachev return NULL; 493b843c749SSergey Zigachev } 494b843c749SSergey Zigachev 495b843c749SSergey Zigachev cgs_device->base.ops = &amdgpu_cgs_ops; 496b843c749SSergey Zigachev cgs_device->adev = adev; 497b843c749SSergey Zigachev 498b843c749SSergey Zigachev return (struct cgs_device *)cgs_device; 499b843c749SSergey Zigachev } 500b843c749SSergey Zigachev 501b843c749SSergey Zigachev void amdgpu_cgs_destroy_device(struct cgs_device *cgs_device) 502b843c749SSergey Zigachev { 503b843c749SSergey Zigachev kfree(cgs_device); 504b843c749SSergey Zigachev } 505