]> Git Repo - linux.git/blob - drivers/gpu/drm/amd/amdgpu/psp_v10_0.c
drm/amdgpu: implement lru amdgpu_queue_mgr policy for compute v4
[linux.git] / drivers / gpu / drm / amd / amdgpu / psp_v10_0.c
1 /*
2  * Copyright 2016 Advanced Micro Devices, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  *
22  * Author: Huang Rui
23  *
24  */
25
26 #include <linux/firmware.h>
27 #include "drmP.h"
28 #include "amdgpu.h"
29 #include "amdgpu_psp.h"
30 #include "amdgpu_ucode.h"
31 #include "soc15_common.h"
32 #include "psp_v10_0.h"
33
34 #include "vega10/soc15ip.h"
35 #include "raven1/MP/mp_10_0_offset.h"
36 #include "raven1/GC/gc_9_1_offset.h"
37 #include "raven1/SDMA0/sdma0_4_1_offset.h"
38
39 static int
40 psp_v10_0_get_fw_type(struct amdgpu_firmware_info *ucode, enum psp_gfx_fw_type *type)
41 {
42         switch(ucode->ucode_id) {
43         case AMDGPU_UCODE_ID_SDMA0:
44                 *type = GFX_FW_TYPE_SDMA0;
45                 break;
46         case AMDGPU_UCODE_ID_SDMA1:
47                 *type = GFX_FW_TYPE_SDMA1;
48                 break;
49         case AMDGPU_UCODE_ID_CP_CE:
50                 *type = GFX_FW_TYPE_CP_CE;
51                 break;
52         case AMDGPU_UCODE_ID_CP_PFP:
53                 *type = GFX_FW_TYPE_CP_PFP;
54                 break;
55         case AMDGPU_UCODE_ID_CP_ME:
56                 *type = GFX_FW_TYPE_CP_ME;
57                 break;
58         case AMDGPU_UCODE_ID_CP_MEC1:
59                 *type = GFX_FW_TYPE_CP_MEC;
60                 break;
61         case AMDGPU_UCODE_ID_CP_MEC1_JT:
62                 *type = GFX_FW_TYPE_CP_MEC_ME1;
63                 break;
64         case AMDGPU_UCODE_ID_CP_MEC2:
65                 *type = GFX_FW_TYPE_CP_MEC;
66                 break;
67         case AMDGPU_UCODE_ID_CP_MEC2_JT:
68                 *type = GFX_FW_TYPE_CP_MEC_ME2;
69                 break;
70         case AMDGPU_UCODE_ID_RLC_G:
71                 *type = GFX_FW_TYPE_RLC_G;
72                 break;
73         case AMDGPU_UCODE_ID_SMC:
74                 *type = GFX_FW_TYPE_SMU;
75                 break;
76         case AMDGPU_UCODE_ID_UVD:
77                 *type = GFX_FW_TYPE_UVD;
78                 break;
79         case AMDGPU_UCODE_ID_VCE:
80                 *type = GFX_FW_TYPE_VCE;
81                 break;
82         case AMDGPU_UCODE_ID_MAXIMUM:
83         default:
84                 return -EINVAL;
85         }
86
87         return 0;
88 }
89
90 int psp_v10_0_prep_cmd_buf(struct amdgpu_firmware_info *ucode, struct psp_gfx_cmd_resp *cmd)
91 {
92         int ret;
93         uint64_t fw_mem_mc_addr = ucode->mc_addr;
94         struct  common_firmware_header *header;
95
96         memset(cmd, 0, sizeof(struct psp_gfx_cmd_resp));
97         header = (struct common_firmware_header *)ucode->fw;
98
99         cmd->cmd_id = GFX_CMD_ID_LOAD_IP_FW;
100         cmd->cmd.cmd_load_ip_fw.fw_phy_addr_lo = (uint32_t)fw_mem_mc_addr;
101         cmd->cmd.cmd_load_ip_fw.fw_phy_addr_hi = (uint32_t)((uint64_t)fw_mem_mc_addr >> 32);
102         cmd->cmd.cmd_load_ip_fw.fw_size = le32_to_cpu(header->ucode_size_bytes);
103
104         ret = psp_v10_0_get_fw_type(ucode, &cmd->cmd.cmd_load_ip_fw.fw_type);
105         if (ret)
106                 DRM_ERROR("Unknown firmware type\n");
107
108         return ret;
109 }
110
111 int psp_v10_0_ring_init(struct psp_context *psp, enum psp_ring_type ring_type)
112 {
113         int ret = 0;
114         unsigned int psp_ring_reg = 0;
115         struct psp_ring *ring;
116         struct amdgpu_device *adev = psp->adev;
117
118         ring = &psp->km_ring;
119
120         ring->ring_type = ring_type;
121
122         /* allocate 4k Page of Local Frame Buffer memory for ring */
123         ring->ring_size = 0x1000;
124         ret = amdgpu_bo_create_kernel(adev, ring->ring_size, PAGE_SIZE,
125                                       AMDGPU_GEM_DOMAIN_VRAM,
126                                       &adev->firmware.rbuf,
127                                       &ring->ring_mem_mc_addr,
128                                       (void **)&ring->ring_mem);
129         if (ret) {
130                 ring->ring_size = 0;
131                 return ret;
132         }
133
134         /* Write low address of the ring to C2PMSG_69 */
135         psp_ring_reg = lower_32_bits(ring->ring_mem_mc_addr);
136         WREG32(SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_69), psp_ring_reg);
137         /* Write high address of the ring to C2PMSG_70 */
138         psp_ring_reg = upper_32_bits(ring->ring_mem_mc_addr);
139         WREG32(SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_70), psp_ring_reg);
140         /* Write size of ring to C2PMSG_71 */
141         psp_ring_reg = ring->ring_size;
142         WREG32(SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_71), psp_ring_reg);
143         /* Write the ring initialization command to C2PMSG_64 */
144         psp_ring_reg = ring_type;
145         psp_ring_reg = psp_ring_reg << 16;
146         WREG32(SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64), psp_ring_reg);
147         /* Wait for response flag (bit 31) in C2PMSG_64 */
148         psp_ring_reg = 0;
149         while ((psp_ring_reg & 0x80000000) == 0) {
150                 psp_ring_reg = RREG32(SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64));
151         }
152
153         return 0;
154 }
155
156 int psp_v10_0_cmd_submit(struct psp_context *psp,
157                         struct amdgpu_firmware_info *ucode,
158                         uint64_t cmd_buf_mc_addr, uint64_t fence_mc_addr,
159                         int index)
160 {
161         unsigned int psp_write_ptr_reg = 0;
162         struct psp_gfx_rb_frame * write_frame = psp->km_ring.ring_mem;
163         struct psp_ring *ring = &psp->km_ring;
164         struct amdgpu_device *adev = psp->adev;
165
166         /* KM (GPCOM) prepare write pointer */
167         psp_write_ptr_reg = RREG32(SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_67));
168
169         /* Update KM RB frame pointer to new frame */
170         if ((psp_write_ptr_reg % ring->ring_size) == 0)
171                 write_frame = ring->ring_mem;
172         else
173                 write_frame = ring->ring_mem + (psp_write_ptr_reg / (sizeof(struct psp_gfx_rb_frame) / 4));
174
175         /* Update KM RB frame */
176         write_frame->cmd_buf_addr_hi = (unsigned int)(cmd_buf_mc_addr >> 32);
177         write_frame->cmd_buf_addr_lo = (unsigned int)(cmd_buf_mc_addr);
178         write_frame->fence_addr_hi = (unsigned int)(fence_mc_addr >> 32);
179         write_frame->fence_addr_lo = (unsigned int)(fence_mc_addr);
180         write_frame->fence_value = index;
181
182         /* Update the write Pointer in DWORDs */
183         psp_write_ptr_reg += sizeof(struct psp_gfx_rb_frame) / 4;
184         psp_write_ptr_reg = (psp_write_ptr_reg >= ring->ring_size) ? 0 : psp_write_ptr_reg;
185         WREG32(SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_67), psp_write_ptr_reg);
186
187         return 0;
188 }
189
190 static int
191 psp_v10_0_sram_map(unsigned int *sram_offset, unsigned int *sram_addr_reg_offset,
192                   unsigned int *sram_data_reg_offset,
193                   enum AMDGPU_UCODE_ID ucode_id)
194 {
195         int ret = 0;
196
197         switch(ucode_id) {
198 /* TODO: needs to confirm */
199 #if 0
200         case AMDGPU_UCODE_ID_SMC:
201                 *sram_offset = 0;
202                 *sram_addr_reg_offset = 0;
203                 *sram_data_reg_offset = 0;
204                 break;
205 #endif
206
207         case AMDGPU_UCODE_ID_CP_CE:
208                 *sram_offset = 0x0;
209                 *sram_addr_reg_offset = SOC15_REG_OFFSET(GC, 0, mmCP_CE_UCODE_ADDR);
210                 *sram_data_reg_offset = SOC15_REG_OFFSET(GC, 0, mmCP_CE_UCODE_DATA);
211                 break;
212
213         case AMDGPU_UCODE_ID_CP_PFP:
214                 *sram_offset = 0x0;
215                 *sram_addr_reg_offset = SOC15_REG_OFFSET(GC, 0, mmCP_PFP_UCODE_ADDR);
216                 *sram_data_reg_offset = SOC15_REG_OFFSET(GC, 0, mmCP_PFP_UCODE_DATA);
217                 break;
218
219         case AMDGPU_UCODE_ID_CP_ME:
220                 *sram_offset = 0x0;
221                 *sram_addr_reg_offset = SOC15_REG_OFFSET(GC, 0, mmCP_HYP_ME_UCODE_ADDR);
222                 *sram_data_reg_offset = SOC15_REG_OFFSET(GC, 0, mmCP_HYP_ME_UCODE_DATA);
223                 break;
224
225         case AMDGPU_UCODE_ID_CP_MEC1:
226                 *sram_offset = 0x10000;
227                 *sram_addr_reg_offset = SOC15_REG_OFFSET(GC, 0, mmCP_MEC_ME1_UCODE_ADDR);
228                 *sram_data_reg_offset = SOC15_REG_OFFSET(GC, 0, mmCP_MEC_ME1_UCODE_DATA);
229                 break;
230
231         case AMDGPU_UCODE_ID_CP_MEC2:
232                 *sram_offset = 0x10000;
233                 *sram_addr_reg_offset = SOC15_REG_OFFSET(GC, 0, mmCP_HYP_MEC2_UCODE_ADDR);
234                 *sram_data_reg_offset = SOC15_REG_OFFSET(GC, 0, mmCP_HYP_MEC2_UCODE_DATA);
235                 break;
236
237         case AMDGPU_UCODE_ID_RLC_G:
238                 *sram_offset = 0x2000;
239                 *sram_addr_reg_offset = SOC15_REG_OFFSET(GC, 0, mmRLC_GPM_UCODE_ADDR);
240                 *sram_data_reg_offset = SOC15_REG_OFFSET(GC, 0, mmRLC_GPM_UCODE_DATA);
241                 break;
242
243         case AMDGPU_UCODE_ID_SDMA0:
244                 *sram_offset = 0x0;
245                 *sram_addr_reg_offset = SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_UCODE_ADDR);
246                 *sram_data_reg_offset = SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_UCODE_DATA);
247                 break;
248
249 /* TODO: needs to confirm */
250 #if 0
251         case AMDGPU_UCODE_ID_SDMA1:
252                 *sram_offset = ;
253                 *sram_addr_reg_offset = ;
254                 break;
255
256         case AMDGPU_UCODE_ID_UVD:
257                 *sram_offset = ;
258                 *sram_addr_reg_offset = ;
259                 break;
260
261         case AMDGPU_UCODE_ID_VCE:
262                 *sram_offset = ;
263                 *sram_addr_reg_offset = ;
264                 break;
265 #endif
266
267         case AMDGPU_UCODE_ID_MAXIMUM:
268         default:
269                 ret = -EINVAL;
270                 break;
271         }
272
273         return ret;
274 }
275
276 bool psp_v10_0_compare_sram_data(struct psp_context *psp,
277                                 struct amdgpu_firmware_info *ucode,
278                                 enum AMDGPU_UCODE_ID ucode_type)
279 {
280         int err = 0;
281         unsigned int fw_sram_reg_val = 0;
282         unsigned int fw_sram_addr_reg_offset = 0;
283         unsigned int fw_sram_data_reg_offset = 0;
284         unsigned int ucode_size;
285         uint32_t *ucode_mem = NULL;
286         struct amdgpu_device *adev = psp->adev;
287
288         err = psp_v10_0_sram_map(&fw_sram_reg_val, &fw_sram_addr_reg_offset,
289                                 &fw_sram_data_reg_offset, ucode_type);
290         if (err)
291                 return false;
292
293         WREG32(fw_sram_addr_reg_offset, fw_sram_reg_val);
294
295         ucode_size = ucode->ucode_size;
296         ucode_mem = (uint32_t *)ucode->kaddr;
297         while (!ucode_size) {
298                 fw_sram_reg_val = RREG32(fw_sram_data_reg_offset);
299
300                 if (*ucode_mem != fw_sram_reg_val)
301                         return false;
302
303                 ucode_mem++;
304                 /* 4 bytes */
305                 ucode_size -= 4;
306         }
307
308         return true;
309 }
This page took 0.056174 seconds and 4 git commands to generate.