1d03846afSChunming Zhou /*
2d03846afSChunming Zhou * Copyright 2015 Advanced Micro Devices, Inc.
3d03846afSChunming Zhou *
4d03846afSChunming Zhou * Permission is hereby granted, free of charge, to any person obtaining a
5d03846afSChunming Zhou * copy of this software and associated documentation files (the "Software"),
6d03846afSChunming Zhou * to deal in the Software without restriction, including without limitation
7d03846afSChunming Zhou * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8d03846afSChunming Zhou * and/or sell copies of the Software, and to permit persons to whom the
9d03846afSChunming Zhou * Software is furnished to do so, subject to the following conditions:
10d03846afSChunming Zhou *
11d03846afSChunming Zhou * The above copyright notice and this permission notice shall be included in
12d03846afSChunming Zhou * all copies or substantial portions of the Software.
13d03846afSChunming Zhou *
14d03846afSChunming Zhou * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15d03846afSChunming Zhou * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16d03846afSChunming Zhou * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17d03846afSChunming Zhou * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18d03846afSChunming Zhou * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19d03846afSChunming Zhou * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20d03846afSChunming Zhou * OTHER DEALINGS IN THE SOFTWARE.
21d03846afSChunming Zhou *
22d03846afSChunming Zhou *
23d03846afSChunming Zhou */
2457ff96cfSChunming Zhou #include <linux/list.h>
25fdf2f6c5SSam Ravnborg #include <linux/pci.h>
2657ff96cfSChunming Zhou #include <linux/slab.h>
27fdf2f6c5SSam Ravnborg
28bf3911b0SJammy Zhou #include <linux/firmware.h>
2957ff96cfSChunming Zhou #include <drm/amdgpu_drm.h>
30d03846afSChunming Zhou #include "amdgpu.h"
3125da4427SChunming Zhou #include "atom.h"
32bf3911b0SJammy Zhou #include "amdgpu_ucode.h"
33bf3911b0SJammy Zhou
34d03846afSChunming Zhou struct amdgpu_cgs_device {
35d03846afSChunming Zhou struct cgs_device base;
36d03846afSChunming Zhou struct amdgpu_device *adev;
37d03846afSChunming Zhou };
38d03846afSChunming Zhou
39d03846afSChunming Zhou #define CGS_FUNC_ADEV \
40d03846afSChunming Zhou struct amdgpu_device *adev = \
41d03846afSChunming Zhou ((struct amdgpu_cgs_device *)cgs_device)->adev
42d03846afSChunming Zhou
43ba89a3ecSRex Zhu
amdgpu_cgs_read_register(struct cgs_device * cgs_device,unsigned int offset)445f95f003SSrinivasan Shanmugam static uint32_t amdgpu_cgs_read_register(struct cgs_device *cgs_device, unsigned int offset)
45d03846afSChunming Zhou {
46aba684d8SChunming Zhou CGS_FUNC_ADEV;
47aba684d8SChunming Zhou return RREG32(offset);
48d03846afSChunming Zhou }
49d03846afSChunming Zhou
amdgpu_cgs_write_register(struct cgs_device * cgs_device,unsigned int offset,uint32_t value)505f95f003SSrinivasan Shanmugam static void amdgpu_cgs_write_register(struct cgs_device *cgs_device, unsigned int offset,
51d03846afSChunming Zhou uint32_t value)
52d03846afSChunming Zhou {
53aba684d8SChunming Zhou CGS_FUNC_ADEV;
54aba684d8SChunming Zhou WREG32(offset, value);
55d03846afSChunming Zhou }
56d03846afSChunming Zhou
amdgpu_cgs_read_ind_register(struct cgs_device * cgs_device,enum cgs_ind_reg space,unsigned int index)57110e6f26SDave Airlie static uint32_t amdgpu_cgs_read_ind_register(struct cgs_device *cgs_device,
58d03846afSChunming Zhou enum cgs_ind_reg space,
595f95f003SSrinivasan Shanmugam unsigned int index)
60d03846afSChunming Zhou {
61aba684d8SChunming Zhou CGS_FUNC_ADEV;
62aba684d8SChunming Zhou switch (space) {
63aba684d8SChunming Zhou case CGS_IND_REG__PCIE:
64aba684d8SChunming Zhou return RREG32_PCIE(index);
65aba684d8SChunming Zhou case CGS_IND_REG__SMC:
66aba684d8SChunming Zhou return RREG32_SMC(index);
67aba684d8SChunming Zhou case CGS_IND_REG__UVD_CTX:
68aba684d8SChunming Zhou return RREG32_UVD_CTX(index);
69aba684d8SChunming Zhou case CGS_IND_REG__DIDT:
70aba684d8SChunming Zhou return RREG32_DIDT(index);
71ccdbb20aSRex Zhu case CGS_IND_REG_GC_CAC:
72ccdbb20aSRex Zhu return RREG32_GC_CAC(index);
73c62a59d0SEvan Quan case CGS_IND_REG_SE_CAC:
74c62a59d0SEvan Quan return RREG32_SE_CAC(index);
75aba684d8SChunming Zhou case CGS_IND_REG__AUDIO_ENDPT:
76aba684d8SChunming Zhou DRM_ERROR("audio endpt register access not implemented.\n");
77aba684d8SChunming Zhou return 0;
783c888c16SHawking Zhang default:
793c888c16SHawking Zhang BUG();
80aba684d8SChunming Zhou }
81aba684d8SChunming Zhou WARN(1, "Invalid indirect register space");
82d03846afSChunming Zhou return 0;
83d03846afSChunming Zhou }
84d03846afSChunming Zhou
amdgpu_cgs_write_ind_register(struct cgs_device * cgs_device,enum cgs_ind_reg space,unsigned int index,uint32_t value)85110e6f26SDave Airlie static void amdgpu_cgs_write_ind_register(struct cgs_device *cgs_device,
86d03846afSChunming Zhou enum cgs_ind_reg space,
875f95f003SSrinivasan Shanmugam unsigned int index, uint32_t value)
88d03846afSChunming Zhou {
89aba684d8SChunming Zhou CGS_FUNC_ADEV;
90aba684d8SChunming Zhou switch (space) {
91aba684d8SChunming Zhou case CGS_IND_REG__PCIE:
92aba684d8SChunming Zhou return WREG32_PCIE(index, value);
93aba684d8SChunming Zhou case CGS_IND_REG__SMC:
94aba684d8SChunming Zhou return WREG32_SMC(index, value);
95aba684d8SChunming Zhou case CGS_IND_REG__UVD_CTX:
96aba684d8SChunming Zhou return WREG32_UVD_CTX(index, value);
97aba684d8SChunming Zhou case CGS_IND_REG__DIDT:
98aba684d8SChunming Zhou return WREG32_DIDT(index, value);
99ccdbb20aSRex Zhu case CGS_IND_REG_GC_CAC:
100ccdbb20aSRex Zhu return WREG32_GC_CAC(index, value);
101c62a59d0SEvan Quan case CGS_IND_REG_SE_CAC:
102c62a59d0SEvan Quan return WREG32_SE_CAC(index, value);
103aba684d8SChunming Zhou case CGS_IND_REG__AUDIO_ENDPT:
104aba684d8SChunming Zhou DRM_ERROR("audio endpt register access not implemented.\n");
105d03846afSChunming Zhou return;
1063c888c16SHawking Zhang default:
1073c888c16SHawking Zhang BUG();
108d03846afSChunming Zhou }
109aba684d8SChunming Zhou WARN(1, "Invalid indirect register space");
110aba684d8SChunming Zhou }
111d03846afSChunming Zhou
fw_type_convert(struct cgs_device * cgs_device,uint32_t fw_type)112110e6f26SDave Airlie static uint32_t fw_type_convert(struct cgs_device *cgs_device, uint32_t fw_type)
113bf3911b0SJammy Zhou {
114bf3911b0SJammy Zhou CGS_FUNC_ADEV;
115bf3911b0SJammy Zhou enum AMDGPU_UCODE_ID result = AMDGPU_UCODE_ID_MAXIMUM;
116bf3911b0SJammy Zhou
117bf3911b0SJammy Zhou switch (fw_type) {
118bf3911b0SJammy Zhou case CGS_UCODE_ID_SDMA0:
119bf3911b0SJammy Zhou result = AMDGPU_UCODE_ID_SDMA0;
120bf3911b0SJammy Zhou break;
121bf3911b0SJammy Zhou case CGS_UCODE_ID_SDMA1:
122bf3911b0SJammy Zhou result = AMDGPU_UCODE_ID_SDMA1;
123bf3911b0SJammy Zhou break;
124bf3911b0SJammy Zhou case CGS_UCODE_ID_CP_CE:
125bf3911b0SJammy Zhou result = AMDGPU_UCODE_ID_CP_CE;
126bf3911b0SJammy Zhou break;
127bf3911b0SJammy Zhou case CGS_UCODE_ID_CP_PFP:
128bf3911b0SJammy Zhou result = AMDGPU_UCODE_ID_CP_PFP;
129bf3911b0SJammy Zhou break;
130bf3911b0SJammy Zhou case CGS_UCODE_ID_CP_ME:
131bf3911b0SJammy Zhou result = AMDGPU_UCODE_ID_CP_ME;
132bf3911b0SJammy Zhou break;
133bf3911b0SJammy Zhou case CGS_UCODE_ID_CP_MEC:
134bf3911b0SJammy Zhou case CGS_UCODE_ID_CP_MEC_JT1:
135bf3911b0SJammy Zhou result = AMDGPU_UCODE_ID_CP_MEC1;
136bf3911b0SJammy Zhou break;
137bf3911b0SJammy Zhou case CGS_UCODE_ID_CP_MEC_JT2:
1384c2b2453SMonk Liu /* for VI. JT2 should be the same as JT1, because:
1394c2b2453SMonk Liu 1, MEC2 and MEC1 use exactly same FW.
1404c2b2453SMonk Liu 2, JT2 is not pached but JT1 is.
1414c2b2453SMonk Liu */
1424c2b2453SMonk Liu if (adev->asic_type >= CHIP_TOPAZ)
143bf3911b0SJammy Zhou result = AMDGPU_UCODE_ID_CP_MEC1;
1444c2b2453SMonk Liu else
1454c2b2453SMonk Liu result = AMDGPU_UCODE_ID_CP_MEC2;
146bf3911b0SJammy Zhou break;
147bf3911b0SJammy Zhou case CGS_UCODE_ID_RLC_G:
148bf3911b0SJammy Zhou result = AMDGPU_UCODE_ID_RLC_G;
149bf3911b0SJammy Zhou break;
150bed5712eSMonk Liu case CGS_UCODE_ID_STORAGE:
151bed5712eSMonk Liu result = AMDGPU_UCODE_ID_STORAGE;
152bed5712eSMonk Liu break;
153bf3911b0SJammy Zhou default:
154bf3911b0SJammy Zhou DRM_ERROR("Firmware type not supported\n");
155bf3911b0SJammy Zhou }
156bf3911b0SJammy Zhou return result;
157bf3911b0SJammy Zhou }
158bf3911b0SJammy Zhou
amdgpu_get_firmware_version(struct cgs_device * cgs_device,enum cgs_ucode_id type)159fc76cbf4SFrank Min static uint16_t amdgpu_get_firmware_version(struct cgs_device *cgs_device,
160fc76cbf4SFrank Min enum cgs_ucode_id type)
161fc76cbf4SFrank Min {
162fc76cbf4SFrank Min CGS_FUNC_ADEV;
163188a301fSXiangliang Yu uint16_t fw_version = 0;
164fc76cbf4SFrank Min
165fc76cbf4SFrank Min switch (type) {
166fc76cbf4SFrank Min case CGS_UCODE_ID_SDMA0:
167fc76cbf4SFrank Min fw_version = adev->sdma.instance[0].fw_version;
168fc76cbf4SFrank Min break;
169fc76cbf4SFrank Min case CGS_UCODE_ID_SDMA1:
170fc76cbf4SFrank Min fw_version = adev->sdma.instance[1].fw_version;
171fc76cbf4SFrank Min break;
172fc76cbf4SFrank Min case CGS_UCODE_ID_CP_CE:
173fc76cbf4SFrank Min fw_version = adev->gfx.ce_fw_version;
174fc76cbf4SFrank Min break;
175fc76cbf4SFrank Min case CGS_UCODE_ID_CP_PFP:
176fc76cbf4SFrank Min fw_version = adev->gfx.pfp_fw_version;
177fc76cbf4SFrank Min break;
178fc76cbf4SFrank Min case CGS_UCODE_ID_CP_ME:
179fc76cbf4SFrank Min fw_version = adev->gfx.me_fw_version;
180fc76cbf4SFrank Min break;
181fc76cbf4SFrank Min case CGS_UCODE_ID_CP_MEC:
182fc76cbf4SFrank Min fw_version = adev->gfx.mec_fw_version;
183fc76cbf4SFrank Min break;
184fc76cbf4SFrank Min case CGS_UCODE_ID_CP_MEC_JT1:
185fc76cbf4SFrank Min fw_version = adev->gfx.mec_fw_version;
186fc76cbf4SFrank Min break;
187fc76cbf4SFrank Min case CGS_UCODE_ID_CP_MEC_JT2:
188fc76cbf4SFrank Min fw_version = adev->gfx.mec_fw_version;
189fc76cbf4SFrank Min break;
190fc76cbf4SFrank Min case CGS_UCODE_ID_RLC_G:
191fc76cbf4SFrank Min fw_version = adev->gfx.rlc_fw_version;
192fc76cbf4SFrank Min break;
193188a301fSXiangliang Yu case CGS_UCODE_ID_STORAGE:
194188a301fSXiangliang Yu break;
195fc76cbf4SFrank Min default:
196fc76cbf4SFrank Min DRM_ERROR("firmware type %d do not have version\n", type);
197188a301fSXiangliang Yu break;
198fc76cbf4SFrank Min }
199fc76cbf4SFrank Min return fw_version;
200fc76cbf4SFrank Min }
201fc76cbf4SFrank Min
amdgpu_cgs_get_firmware_info(struct cgs_device * cgs_device,enum cgs_ucode_id type,struct cgs_firmware_info * info)202110e6f26SDave Airlie static int amdgpu_cgs_get_firmware_info(struct cgs_device *cgs_device,
203bf3911b0SJammy Zhou enum cgs_ucode_id type,
204bf3911b0SJammy Zhou struct cgs_firmware_info *info)
205bf3911b0SJammy Zhou {
206bf3911b0SJammy Zhou CGS_FUNC_ADEV;
207bf3911b0SJammy Zhou
2085f95f003SSrinivasan Shanmugam if (type != CGS_UCODE_ID_SMU && type != CGS_UCODE_ID_SMU_SK) {
209bf3911b0SJammy Zhou uint64_t gpu_addr;
210bf3911b0SJammy Zhou uint32_t data_size;
211bf3911b0SJammy Zhou const struct gfx_firmware_header_v1_0 *header;
212bf3911b0SJammy Zhou enum AMDGPU_UCODE_ID id;
213bf3911b0SJammy Zhou struct amdgpu_firmware_info *ucode;
214bf3911b0SJammy Zhou
215bf3911b0SJammy Zhou id = fw_type_convert(cgs_device, type);
2168944acd0STim Huang if (id >= AMDGPU_UCODE_ID_MAXIMUM)
2178944acd0STim Huang return -EINVAL;
2188944acd0STim Huang
219bf3911b0SJammy Zhou ucode = &adev->firmware.ucode[id];
220bf3911b0SJammy Zhou if (ucode->fw == NULL)
221bf3911b0SJammy Zhou return -EINVAL;
222bf3911b0SJammy Zhou
223bf3911b0SJammy Zhou gpu_addr = ucode->mc_addr;
224bf3911b0SJammy Zhou header = (const struct gfx_firmware_header_v1_0 *)ucode->fw->data;
225bf3911b0SJammy Zhou data_size = le32_to_cpu(header->header.ucode_size_bytes);
226bf3911b0SJammy Zhou
227bf3911b0SJammy Zhou if ((type == CGS_UCODE_ID_CP_MEC_JT1) ||
228bf3911b0SJammy Zhou (type == CGS_UCODE_ID_CP_MEC_JT2)) {
2294c2b2453SMonk Liu gpu_addr += ALIGN(le32_to_cpu(header->header.ucode_size_bytes), PAGE_SIZE);
230bf3911b0SJammy Zhou data_size = le32_to_cpu(header->jt_size) << 2;
231bf3911b0SJammy Zhou }
2324c2b2453SMonk Liu
2334c2b2453SMonk Liu info->kptr = ucode->kaddr;
234bf3911b0SJammy Zhou info->image_size = data_size;
2354c2b2453SMonk Liu info->mc_addr = gpu_addr;
236bf3911b0SJammy Zhou info->version = (uint16_t)le32_to_cpu(header->header.ucode_version);
2374c2b2453SMonk Liu
2385f95f003SSrinivasan Shanmugam if (type == CGS_UCODE_ID_CP_MEC)
239e68760bfSEvan Quan info->image_size = le32_to_cpu(header->jt_offset) << 2;
2404c2b2453SMonk Liu
241fc76cbf4SFrank Min info->fw_version = amdgpu_get_firmware_version(cgs_device, type);
242bf3911b0SJammy Zhou info->feature_version = (uint16_t)le32_to_cpu(header->ucode_feature_version);
243bf3911b0SJammy Zhou } else {
244bf3911b0SJammy Zhou char fw_name[30] = {0};
245bf3911b0SJammy Zhou int err = 0;
246bf3911b0SJammy Zhou uint32_t ucode_size;
247bf3911b0SJammy Zhou uint32_t ucode_start_address;
248bf3911b0SJammy Zhou const uint8_t *src;
249bf3911b0SJammy Zhou const struct smc_firmware_header_v1_0 *hdr;
250d1de1ed3SHuang Rui const struct common_firmware_header *header;
251d1de1ed3SHuang Rui struct amdgpu_firmware_info *ucode = NULL;
252bf3911b0SJammy Zhou
2530b45541dSMykola Lysenko if (!adev->pm.fw) {
254bf3911b0SJammy Zhou switch (adev->asic_type) {
2556df9855fSRex Zhu case CHIP_TAHITI:
2566df9855fSRex Zhu strcpy(fw_name, "radeon/tahiti_smc.bin");
2576df9855fSRex Zhu break;
2586df9855fSRex Zhu case CHIP_PITCAIRN:
2596df9855fSRex Zhu if ((adev->pdev->revision == 0x81) &&
2606df9855fSRex Zhu ((adev->pdev->device == 0x6810) ||
2616df9855fSRex Zhu (adev->pdev->device == 0x6811))) {
2626df9855fSRex Zhu info->is_kicker = true;
2636df9855fSRex Zhu strcpy(fw_name, "radeon/pitcairn_k_smc.bin");
2646df9855fSRex Zhu } else {
2656df9855fSRex Zhu strcpy(fw_name, "radeon/pitcairn_smc.bin");
2666df9855fSRex Zhu }
2676df9855fSRex Zhu break;
2686df9855fSRex Zhu case CHIP_VERDE:
2696df9855fSRex Zhu if (((adev->pdev->device == 0x6820) &&
2706df9855fSRex Zhu ((adev->pdev->revision == 0x81) ||
2716df9855fSRex Zhu (adev->pdev->revision == 0x83))) ||
2726df9855fSRex Zhu ((adev->pdev->device == 0x6821) &&
2736df9855fSRex Zhu ((adev->pdev->revision == 0x83) ||
2746df9855fSRex Zhu (adev->pdev->revision == 0x87))) ||
2756df9855fSRex Zhu ((adev->pdev->revision == 0x87) &&
2766df9855fSRex Zhu ((adev->pdev->device == 0x6823) ||
2776df9855fSRex Zhu (adev->pdev->device == 0x682b)))) {
2786df9855fSRex Zhu info->is_kicker = true;
2796df9855fSRex Zhu strcpy(fw_name, "radeon/verde_k_smc.bin");
2806df9855fSRex Zhu } else {
2816df9855fSRex Zhu strcpy(fw_name, "radeon/verde_smc.bin");
2826df9855fSRex Zhu }
2836df9855fSRex Zhu break;
2846df9855fSRex Zhu case CHIP_OLAND:
2856df9855fSRex Zhu if (((adev->pdev->revision == 0x81) &&
2866df9855fSRex Zhu ((adev->pdev->device == 0x6600) ||
2876df9855fSRex Zhu (adev->pdev->device == 0x6604) ||
2886df9855fSRex Zhu (adev->pdev->device == 0x6605) ||
2896df9855fSRex Zhu (adev->pdev->device == 0x6610))) ||
2906df9855fSRex Zhu ((adev->pdev->revision == 0x83) &&
2916df9855fSRex Zhu (adev->pdev->device == 0x6610))) {
2926df9855fSRex Zhu info->is_kicker = true;
2936df9855fSRex Zhu strcpy(fw_name, "radeon/oland_k_smc.bin");
2946df9855fSRex Zhu } else {
2956df9855fSRex Zhu strcpy(fw_name, "radeon/oland_smc.bin");
2966df9855fSRex Zhu }
2976df9855fSRex Zhu break;
2986df9855fSRex Zhu case CHIP_HAINAN:
2996df9855fSRex Zhu if (((adev->pdev->revision == 0x81) &&
3006df9855fSRex Zhu (adev->pdev->device == 0x6660)) ||
3016df9855fSRex Zhu ((adev->pdev->revision == 0x83) &&
3026df9855fSRex Zhu ((adev->pdev->device == 0x6660) ||
3036df9855fSRex Zhu (adev->pdev->device == 0x6663) ||
3046df9855fSRex Zhu (adev->pdev->device == 0x6665) ||
3056df9855fSRex Zhu (adev->pdev->device == 0x6667)))) {
3066df9855fSRex Zhu info->is_kicker = true;
3076df9855fSRex Zhu strcpy(fw_name, "radeon/hainan_k_smc.bin");
3086df9855fSRex Zhu } else if ((adev->pdev->revision == 0xc3) &&
3096df9855fSRex Zhu (adev->pdev->device == 0x6665)) {
3106df9855fSRex Zhu info->is_kicker = true;
3116df9855fSRex Zhu strcpy(fw_name, "radeon/banks_k_2_smc.bin");
3126df9855fSRex Zhu } else {
3136df9855fSRex Zhu strcpy(fw_name, "radeon/hainan_smc.bin");
3146df9855fSRex Zhu }
3156df9855fSRex Zhu break;
3166df9855fSRex Zhu case CHIP_BONAIRE:
3176df9855fSRex Zhu if ((adev->pdev->revision == 0x80) ||
3186df9855fSRex Zhu (adev->pdev->revision == 0x81) ||
3196df9855fSRex Zhu (adev->pdev->device == 0x665f)) {
3206df9855fSRex Zhu info->is_kicker = true;
321ce206464SAlex Deucher strcpy(fw_name, "amdgpu/bonaire_k_smc.bin");
3226df9855fSRex Zhu } else {
323ce206464SAlex Deucher strcpy(fw_name, "amdgpu/bonaire_smc.bin");
3246df9855fSRex Zhu }
3256df9855fSRex Zhu break;
3266df9855fSRex Zhu case CHIP_HAWAII:
3276df9855fSRex Zhu if (adev->pdev->revision == 0x80) {
3286df9855fSRex Zhu info->is_kicker = true;
329ce206464SAlex Deucher strcpy(fw_name, "amdgpu/hawaii_k_smc.bin");
3306df9855fSRex Zhu } else {
331ce206464SAlex Deucher strcpy(fw_name, "amdgpu/hawaii_smc.bin");
3326df9855fSRex Zhu }
3336df9855fSRex Zhu break;
334340efe28SHuang Rui case CHIP_TOPAZ:
3353b496626SAlex Deucher if (((adev->pdev->device == 0x6900) && (adev->pdev->revision == 0x81)) ||
3363b496626SAlex Deucher ((adev->pdev->device == 0x6900) && (adev->pdev->revision == 0x83)) ||
337153573d8SAlex Deucher ((adev->pdev->device == 0x6907) && (adev->pdev->revision == 0x87)) ||
338153573d8SAlex Deucher ((adev->pdev->device == 0x6900) && (adev->pdev->revision == 0xD1)) ||
339153573d8SAlex Deucher ((adev->pdev->device == 0x6900) && (adev->pdev->revision == 0xD3))) {
3405d7213b0SHuang Rui info->is_kicker = true;
3413b496626SAlex Deucher strcpy(fw_name, "amdgpu/topaz_k_smc.bin");
3425d7213b0SHuang Rui } else
343340efe28SHuang Rui strcpy(fw_name, "amdgpu/topaz_smc.bin");
344340efe28SHuang Rui break;
345bf3911b0SJammy Zhou case CHIP_TONGA:
346646cccb5SAlex Deucher if (((adev->pdev->device == 0x6939) && (adev->pdev->revision == 0xf1)) ||
3475d7213b0SHuang Rui ((adev->pdev->device == 0x6938) && (adev->pdev->revision == 0xf1))) {
3485d7213b0SHuang Rui info->is_kicker = true;
349646cccb5SAlex Deucher strcpy(fw_name, "amdgpu/tonga_k_smc.bin");
3505d7213b0SHuang Rui } else
351bf3911b0SJammy Zhou strcpy(fw_name, "amdgpu/tonga_smc.bin");
352bf3911b0SJammy Zhou break;
353899fa4c0SEric Huang case CHIP_FIJI:
354899fa4c0SEric Huang strcpy(fw_name, "amdgpu/fiji_smc.bin");
355899fa4c0SEric Huang break;
3562cc0c0b5SFlora Cui case CHIP_POLARIS11:
357a52d120fSAlex Deucher if (type == CGS_UCODE_ID_SMU) {
35873275181SEvan Quan if (ASICID_IS_P21(adev->pdev->device, adev->pdev->revision)) {
3595d7213b0SHuang Rui info->is_kicker = true;
360a52d120fSAlex Deucher strcpy(fw_name, "amdgpu/polaris11_k_smc.bin");
36173275181SEvan Quan } else if (ASICID_IS_P31(adev->pdev->device, adev->pdev->revision)) {
362153573d8SAlex Deucher info->is_kicker = true;
363153573d8SAlex Deucher strcpy(fw_name, "amdgpu/polaris11_k2_smc.bin");
364153573d8SAlex Deucher } else {
3652cc0c0b5SFlora Cui strcpy(fw_name, "amdgpu/polaris11_smc.bin");
366153573d8SAlex Deucher }
367a52d120fSAlex Deucher } else if (type == CGS_UCODE_ID_SMU_SK) {
3682cc0c0b5SFlora Cui strcpy(fw_name, "amdgpu/polaris11_smc_sk.bin");
369a52d120fSAlex Deucher }
370c8172625Srezhu break;
3712cc0c0b5SFlora Cui case CHIP_POLARIS10:
372a52d120fSAlex Deucher if (type == CGS_UCODE_ID_SMU) {
37373275181SEvan Quan if (ASICID_IS_P20(adev->pdev->device, adev->pdev->revision)) {
3745d7213b0SHuang Rui info->is_kicker = true;
375a52d120fSAlex Deucher strcpy(fw_name, "amdgpu/polaris10_k_smc.bin");
37673275181SEvan Quan } else if (ASICID_IS_P30(adev->pdev->device, adev->pdev->revision)) {
377153573d8SAlex Deucher info->is_kicker = true;
378153573d8SAlex Deucher strcpy(fw_name, "amdgpu/polaris10_k2_smc.bin");
379153573d8SAlex Deucher } else {
3802cc0c0b5SFlora Cui strcpy(fw_name, "amdgpu/polaris10_smc.bin");
381153573d8SAlex Deucher }
382a52d120fSAlex Deucher } else if (type == CGS_UCODE_ID_SMU_SK) {
3832cc0c0b5SFlora Cui strcpy(fw_name, "amdgpu/polaris10_smc_sk.bin");
384a52d120fSAlex Deucher }
385c8172625Srezhu break;
386c4642a47SJunwei Zhang case CHIP_POLARIS12:
38773275181SEvan Quan if (ASICID_IS_P23(adev->pdev->device, adev->pdev->revision)) {
388153573d8SAlex Deucher info->is_kicker = true;
389153573d8SAlex Deucher strcpy(fw_name, "amdgpu/polaris12_k_smc.bin");
390153573d8SAlex Deucher } else {
391c4642a47SJunwei Zhang strcpy(fw_name, "amdgpu/polaris12_smc.bin");
392153573d8SAlex Deucher }
393c4642a47SJunwei Zhang break;
3945830bb98SLeo Liu case CHIP_VEGAM:
3955830bb98SLeo Liu strcpy(fw_name, "amdgpu/vegam_smc.bin");
3965830bb98SLeo Liu break;
397220ab9bdSKen Wang case CHIP_VEGA10:
398747f6c92SEvan Quan if ((adev->pdev->device == 0x687f) &&
399747f6c92SEvan Quan ((adev->pdev->revision == 0xc0) ||
400747f6c92SEvan Quan (adev->pdev->revision == 0xc1) ||
401747f6c92SEvan Quan (adev->pdev->revision == 0xc3)))
402747f6c92SEvan Quan strcpy(fw_name, "amdgpu/vega10_acg_smc.bin");
403747f6c92SEvan Quan else
404220ab9bdSKen Wang strcpy(fw_name, "amdgpu/vega10_smc.bin");
405220ab9bdSKen Wang break;
406ad0ad9aaSHawking Zhang case CHIP_VEGA12:
407ad0ad9aaSHawking Zhang strcpy(fw_name, "amdgpu/vega12_smc.bin");
408ad0ad9aaSHawking Zhang break;
409a167ae25SFeifei Xu case CHIP_VEGA20:
410a167ae25SFeifei Xu strcpy(fw_name, "amdgpu/vega20_smc.bin");
411a167ae25SFeifei Xu break;
412bf3911b0SJammy Zhou default:
413bf3911b0SJammy Zhou DRM_ERROR("SMC firmware not supported\n");
414bf3911b0SJammy Zhou return -EINVAL;
415bf3911b0SJammy Zhou }
416bf3911b0SJammy Zhou
417*ea5d4934SMario Limonciello err = amdgpu_ucode_request(adev, &adev->pm.fw,
418*ea5d4934SMario Limonciello AMDGPU_UCODE_REQUIRED,
419*ea5d4934SMario Limonciello "%s", fw_name);
420bf3911b0SJammy Zhou if (err) {
421bf3911b0SJammy Zhou DRM_ERROR("Failed to load firmware \"%s\"", fw_name);
422e5a7d047SMario Limonciello amdgpu_ucode_release(&adev->pm.fw);
423bf3911b0SJammy Zhou return err;
424bf3911b0SJammy Zhou }
425d1de1ed3SHuang Rui
426d1de1ed3SHuang Rui if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
427d1de1ed3SHuang Rui ucode = &adev->firmware.ucode[AMDGPU_UCODE_ID_SMC];
428d1de1ed3SHuang Rui ucode->ucode_id = AMDGPU_UCODE_ID_SMC;
429d1de1ed3SHuang Rui ucode->fw = adev->pm.fw;
430d1de1ed3SHuang Rui header = (const struct common_firmware_header *)ucode->fw->data;
431d1de1ed3SHuang Rui adev->firmware.fw_size +=
432d1de1ed3SHuang Rui ALIGN(le32_to_cpu(header->ucode_size_bytes), PAGE_SIZE);
433d1de1ed3SHuang Rui }
4340b45541dSMykola Lysenko }
435bf3911b0SJammy Zhou
436bf3911b0SJammy Zhou hdr = (const struct smc_firmware_header_v1_0 *) adev->pm.fw->data;
437c66875b1Syanyang1 amdgpu_ucode_print_smc_hdr(&hdr->header);
438bf3911b0SJammy Zhou adev->pm.fw_version = le32_to_cpu(hdr->header.ucode_version);
439bf3911b0SJammy Zhou ucode_size = le32_to_cpu(hdr->header.ucode_size_bytes);
440bf3911b0SJammy Zhou ucode_start_address = le32_to_cpu(hdr->ucode_start_addr);
441bf3911b0SJammy Zhou src = (const uint8_t *)(adev->pm.fw->data +
442bf3911b0SJammy Zhou le32_to_cpu(hdr->header.ucode_array_offset_bytes));
443bf3911b0SJammy Zhou
444bf3911b0SJammy Zhou info->version = adev->pm.fw_version;
445bf3911b0SJammy Zhou info->image_size = ucode_size;
446340efe28SHuang Rui info->ucode_start_address = ucode_start_address;
447bf3911b0SJammy Zhou info->kptr = (void *)src;
448bf3911b0SJammy Zhou }
449bf3911b0SJammy Zhou return 0;
450bf3911b0SJammy Zhou }
451bf3911b0SJammy Zhou
452d03846afSChunming Zhou static const struct cgs_ops amdgpu_cgs_ops = {
453613e61a0SKees Cook .read_register = amdgpu_cgs_read_register,
454613e61a0SKees Cook .write_register = amdgpu_cgs_write_register,
455613e61a0SKees Cook .read_ind_register = amdgpu_cgs_read_ind_register,
456613e61a0SKees Cook .write_ind_register = amdgpu_cgs_write_ind_register,
457613e61a0SKees Cook .get_firmware_info = amdgpu_cgs_get_firmware_info,
458d03846afSChunming Zhou };
459d03846afSChunming Zhou
amdgpu_cgs_create_device(struct amdgpu_device * adev)460110e6f26SDave Airlie struct cgs_device *amdgpu_cgs_create_device(struct amdgpu_device *adev)
461d03846afSChunming Zhou {
462d03846afSChunming Zhou struct amdgpu_cgs_device *cgs_device =
463d03846afSChunming Zhou kmalloc(sizeof(*cgs_device), GFP_KERNEL);
464d03846afSChunming Zhou
465d03846afSChunming Zhou if (!cgs_device) {
466d03846afSChunming Zhou DRM_ERROR("Couldn't allocate CGS device structure\n");
467d03846afSChunming Zhou return NULL;
468d03846afSChunming Zhou }
469d03846afSChunming Zhou
470d03846afSChunming Zhou cgs_device->base.ops = &amdgpu_cgs_ops;
471d03846afSChunming Zhou cgs_device->adev = adev;
472d03846afSChunming Zhou
473110e6f26SDave Airlie return (struct cgs_device *)cgs_device;
474d03846afSChunming Zhou }
475d03846afSChunming Zhou
amdgpu_cgs_destroy_device(struct cgs_device * cgs_device)476110e6f26SDave Airlie void amdgpu_cgs_destroy_device(struct cgs_device *cgs_device)
477d03846afSChunming Zhou {
478d03846afSChunming Zhou kfree(cgs_device);
479d03846afSChunming Zhou }
480