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