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