blob: 32252f8ac30c3748b9d2f7d31cd9143ac6ac2295 [file] [log] [blame]
Jordan Crouse2002c9c2017-03-07 09:50:27 -07001/* Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
Jordan Crouseb5f103a2016-11-28 12:28:33 -07002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 */
13
Jordan Crouse7c658172017-05-17 08:45:29 -060014#include <linux/types.h>
15#include <linux/cpumask.h>
16#include <linux/qcom_scm.h>
17#include <linux/dma-mapping.h>
Arnd Bergmann8f93e042017-07-26 21:59:21 +020018#include <linux/of_address.h>
Jordan Crouse7c658172017-05-17 08:45:29 -060019#include <linux/soc/qcom/mdt_loader.h>
Jordan Crouseb5f103a2016-11-28 12:28:33 -070020#include "msm_gem.h"
Rob Clark7f8036b2016-12-07 11:13:53 -050021#include "msm_mmu.h"
Jordan Crouseb5f103a2016-11-28 12:28:33 -070022#include "a5xx_gpu.h"
23
24extern bool hang_debug;
25static void a5xx_dump(struct msm_gpu *gpu);
26
Jordan Crouse7c658172017-05-17 08:45:29 -060027#define GPU_PAS_ID 13
28
Rob Clarke8f3de92017-10-16 10:13:15 -040029static int zap_shader_load_mdt(struct msm_gpu *gpu, const char *fwname)
Jordan Crouse7c658172017-05-17 08:45:29 -060030{
Rob Clarke8f3de92017-10-16 10:13:15 -040031 struct device *dev = &gpu->pdev->dev;
Jordan Crouse7c658172017-05-17 08:45:29 -060032 const struct firmware *fw;
Arnd Bergmann8f93e042017-07-26 21:59:21 +020033 struct device_node *np;
34 struct resource r;
Jordan Crouse7c658172017-05-17 08:45:29 -060035 phys_addr_t mem_phys;
36 ssize_t mem_size;
37 void *mem_region = NULL;
38 int ret;
39
Arnd Bergmannbdab8e82017-07-26 17:52:44 +020040 if (!IS_ENABLED(CONFIG_ARCH_QCOM))
41 return -EINVAL;
42
Arnd Bergmann8f93e042017-07-26 21:59:21 +020043 np = of_get_child_by_name(dev->of_node, "zap-shader");
44 if (!np)
45 return -ENODEV;
46
47 np = of_parse_phandle(np, "memory-region", 0);
48 if (!np)
49 return -EINVAL;
50
51 ret = of_address_to_resource(np, 0, &r);
52 if (ret)
53 return ret;
54
55 mem_phys = r.start;
56 mem_size = resource_size(&r);
57
Jordan Crouse7c658172017-05-17 08:45:29 -060058 /* Request the MDT file for the firmware */
Rob Clarke8f3de92017-10-16 10:13:15 -040059 fw = adreno_request_fw(to_adreno_gpu(gpu), fwname);
60 if (IS_ERR(fw)) {
Jordan Crouse7c658172017-05-17 08:45:29 -060061 DRM_DEV_ERROR(dev, "Unable to load %s\n", fwname);
Rob Clarke8f3de92017-10-16 10:13:15 -040062 return PTR_ERR(fw);
Jordan Crouse7c658172017-05-17 08:45:29 -060063 }
64
65 /* Figure out how much memory we need */
66 mem_size = qcom_mdt_get_size(fw);
67 if (mem_size < 0) {
68 ret = mem_size;
69 goto out;
70 }
71
72 /* Allocate memory for the firmware image */
Arnd Bergmann8f93e042017-07-26 21:59:21 +020073 mem_region = memremap(mem_phys, mem_size, MEMREMAP_WC);
Jordan Crouse7c658172017-05-17 08:45:29 -060074 if (!mem_region) {
75 ret = -ENOMEM;
76 goto out;
77 }
78
Rob Clark2c41ef12017-10-16 10:46:23 -040079 /*
80 * Load the rest of the MDT
81 *
82 * Note that we could be dealing with two different paths, since
83 * with upstream linux-firmware it would be in a qcom/ subdir..
84 * adreno_request_fw() handles this, but qcom_mdt_load() does
85 * not. But since we've already gotten thru adreno_request_fw()
86 * we know which of the two cases it is:
87 */
88 if (to_adreno_gpu(gpu)->fwloc == FW_LOCATION_LEGACY) {
89 ret = qcom_mdt_load(dev, fw, fwname, GPU_PAS_ID,
90 mem_region, mem_phys, mem_size);
91 } else {
92 char newname[strlen("qcom/") + strlen(fwname) + 1];
93
94 sprintf(newname, "qcom/%s", fwname);
95
96 ret = qcom_mdt_load(dev, fw, newname, GPU_PAS_ID,
97 mem_region, mem_phys, mem_size);
98 }
Jordan Crouse7c658172017-05-17 08:45:29 -060099 if (ret)
100 goto out;
101
102 /* Send the image to the secure world */
103 ret = qcom_scm_pas_auth_and_reset(GPU_PAS_ID);
104 if (ret)
105 DRM_DEV_ERROR(dev, "Unable to authorize the image\n");
106
107out:
Arnd Bergmann8f93e042017-07-26 21:59:21 +0200108 if (mem_region)
109 memunmap(mem_region);
110
Jordan Crouse7c658172017-05-17 08:45:29 -0600111 release_firmware(fw);
112
113 return ret;
114}
Jordan Crouse7c658172017-05-17 08:45:29 -0600115
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700116static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
117 struct msm_file_private *ctx)
118{
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700119 struct msm_drm_private *priv = gpu->dev->dev_private;
Jordan Crousef97deca2017-10-20 11:06:57 -0600120 struct msm_ringbuffer *ring = submit->ring;
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700121 unsigned int i, ibs = 0;
122
123 for (i = 0; i < submit->nr_cmds; i++) {
124 switch (submit->cmd[i].type) {
125 case MSM_SUBMIT_CMD_IB_TARGET_BUF:
126 break;
127 case MSM_SUBMIT_CMD_CTX_RESTORE_BUF:
128 if (priv->lastctx == ctx)
129 break;
130 case MSM_SUBMIT_CMD_BUF:
131 OUT_PKT7(ring, CP_INDIRECT_BUFFER_PFE, 3);
132 OUT_RING(ring, lower_32_bits(submit->cmd[i].iova));
133 OUT_RING(ring, upper_32_bits(submit->cmd[i].iova));
134 OUT_RING(ring, submit->cmd[i].size);
135 ibs++;
136 break;
137 }
138 }
139
140 OUT_PKT4(ring, REG_A5XX_CP_SCRATCH_REG(2), 1);
Jordan Crousef97deca2017-10-20 11:06:57 -0600141 OUT_RING(ring, submit->seqno);
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700142
143 OUT_PKT7(ring, CP_EVENT_WRITE, 4);
144 OUT_RING(ring, CACHE_FLUSH_TS | (1 << 31));
Jordan Crousef97deca2017-10-20 11:06:57 -0600145 OUT_RING(ring, lower_32_bits(rbmemptr(ring, fence)));
146 OUT_RING(ring, upper_32_bits(rbmemptr(ring, fence)));
147 OUT_RING(ring, submit->seqno);
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700148
Jordan Crousef97deca2017-10-20 11:06:57 -0600149 gpu->funcs->flush(gpu, ring);
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700150}
151
Jordan Crouse6e749e52017-07-27 10:42:31 -0600152static const struct {
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700153 u32 offset;
154 u32 value;
Jordan Crouse6e749e52017-07-27 10:42:31 -0600155} a5xx_hwcg[] = {
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700156 {REG_A5XX_RBBM_CLOCK_CNTL_SP0, 0x02222222},
157 {REG_A5XX_RBBM_CLOCK_CNTL_SP1, 0x02222222},
158 {REG_A5XX_RBBM_CLOCK_CNTL_SP2, 0x02222222},
159 {REG_A5XX_RBBM_CLOCK_CNTL_SP3, 0x02222222},
160 {REG_A5XX_RBBM_CLOCK_CNTL2_SP0, 0x02222220},
161 {REG_A5XX_RBBM_CLOCK_CNTL2_SP1, 0x02222220},
162 {REG_A5XX_RBBM_CLOCK_CNTL2_SP2, 0x02222220},
163 {REG_A5XX_RBBM_CLOCK_CNTL2_SP3, 0x02222220},
164 {REG_A5XX_RBBM_CLOCK_HYST_SP0, 0x0000F3CF},
165 {REG_A5XX_RBBM_CLOCK_HYST_SP1, 0x0000F3CF},
166 {REG_A5XX_RBBM_CLOCK_HYST_SP2, 0x0000F3CF},
167 {REG_A5XX_RBBM_CLOCK_HYST_SP3, 0x0000F3CF},
168 {REG_A5XX_RBBM_CLOCK_DELAY_SP0, 0x00000080},
169 {REG_A5XX_RBBM_CLOCK_DELAY_SP1, 0x00000080},
170 {REG_A5XX_RBBM_CLOCK_DELAY_SP2, 0x00000080},
171 {REG_A5XX_RBBM_CLOCK_DELAY_SP3, 0x00000080},
172 {REG_A5XX_RBBM_CLOCK_CNTL_TP0, 0x22222222},
173 {REG_A5XX_RBBM_CLOCK_CNTL_TP1, 0x22222222},
174 {REG_A5XX_RBBM_CLOCK_CNTL_TP2, 0x22222222},
175 {REG_A5XX_RBBM_CLOCK_CNTL_TP3, 0x22222222},
176 {REG_A5XX_RBBM_CLOCK_CNTL2_TP0, 0x22222222},
177 {REG_A5XX_RBBM_CLOCK_CNTL2_TP1, 0x22222222},
178 {REG_A5XX_RBBM_CLOCK_CNTL2_TP2, 0x22222222},
179 {REG_A5XX_RBBM_CLOCK_CNTL2_TP3, 0x22222222},
180 {REG_A5XX_RBBM_CLOCK_CNTL3_TP0, 0x00002222},
181 {REG_A5XX_RBBM_CLOCK_CNTL3_TP1, 0x00002222},
182 {REG_A5XX_RBBM_CLOCK_CNTL3_TP2, 0x00002222},
183 {REG_A5XX_RBBM_CLOCK_CNTL3_TP3, 0x00002222},
184 {REG_A5XX_RBBM_CLOCK_HYST_TP0, 0x77777777},
185 {REG_A5XX_RBBM_CLOCK_HYST_TP1, 0x77777777},
186 {REG_A5XX_RBBM_CLOCK_HYST_TP2, 0x77777777},
187 {REG_A5XX_RBBM_CLOCK_HYST_TP3, 0x77777777},
188 {REG_A5XX_RBBM_CLOCK_HYST2_TP0, 0x77777777},
189 {REG_A5XX_RBBM_CLOCK_HYST2_TP1, 0x77777777},
190 {REG_A5XX_RBBM_CLOCK_HYST2_TP2, 0x77777777},
191 {REG_A5XX_RBBM_CLOCK_HYST2_TP3, 0x77777777},
192 {REG_A5XX_RBBM_CLOCK_HYST3_TP0, 0x00007777},
193 {REG_A5XX_RBBM_CLOCK_HYST3_TP1, 0x00007777},
194 {REG_A5XX_RBBM_CLOCK_HYST3_TP2, 0x00007777},
195 {REG_A5XX_RBBM_CLOCK_HYST3_TP3, 0x00007777},
196 {REG_A5XX_RBBM_CLOCK_DELAY_TP0, 0x11111111},
197 {REG_A5XX_RBBM_CLOCK_DELAY_TP1, 0x11111111},
198 {REG_A5XX_RBBM_CLOCK_DELAY_TP2, 0x11111111},
199 {REG_A5XX_RBBM_CLOCK_DELAY_TP3, 0x11111111},
200 {REG_A5XX_RBBM_CLOCK_DELAY2_TP0, 0x11111111},
201 {REG_A5XX_RBBM_CLOCK_DELAY2_TP1, 0x11111111},
202 {REG_A5XX_RBBM_CLOCK_DELAY2_TP2, 0x11111111},
203 {REG_A5XX_RBBM_CLOCK_DELAY2_TP3, 0x11111111},
204 {REG_A5XX_RBBM_CLOCK_DELAY3_TP0, 0x00001111},
205 {REG_A5XX_RBBM_CLOCK_DELAY3_TP1, 0x00001111},
206 {REG_A5XX_RBBM_CLOCK_DELAY3_TP2, 0x00001111},
207 {REG_A5XX_RBBM_CLOCK_DELAY3_TP3, 0x00001111},
208 {REG_A5XX_RBBM_CLOCK_CNTL_UCHE, 0x22222222},
209 {REG_A5XX_RBBM_CLOCK_CNTL2_UCHE, 0x22222222},
210 {REG_A5XX_RBBM_CLOCK_CNTL3_UCHE, 0x22222222},
211 {REG_A5XX_RBBM_CLOCK_CNTL4_UCHE, 0x00222222},
212 {REG_A5XX_RBBM_CLOCK_HYST_UCHE, 0x00444444},
213 {REG_A5XX_RBBM_CLOCK_DELAY_UCHE, 0x00000002},
214 {REG_A5XX_RBBM_CLOCK_CNTL_RB0, 0x22222222},
215 {REG_A5XX_RBBM_CLOCK_CNTL_RB1, 0x22222222},
216 {REG_A5XX_RBBM_CLOCK_CNTL_RB2, 0x22222222},
217 {REG_A5XX_RBBM_CLOCK_CNTL_RB3, 0x22222222},
218 {REG_A5XX_RBBM_CLOCK_CNTL2_RB0, 0x00222222},
219 {REG_A5XX_RBBM_CLOCK_CNTL2_RB1, 0x00222222},
220 {REG_A5XX_RBBM_CLOCK_CNTL2_RB2, 0x00222222},
221 {REG_A5XX_RBBM_CLOCK_CNTL2_RB3, 0x00222222},
222 {REG_A5XX_RBBM_CLOCK_CNTL_CCU0, 0x00022220},
223 {REG_A5XX_RBBM_CLOCK_CNTL_CCU1, 0x00022220},
224 {REG_A5XX_RBBM_CLOCK_CNTL_CCU2, 0x00022220},
225 {REG_A5XX_RBBM_CLOCK_CNTL_CCU3, 0x00022220},
226 {REG_A5XX_RBBM_CLOCK_CNTL_RAC, 0x05522222},
227 {REG_A5XX_RBBM_CLOCK_CNTL2_RAC, 0x00505555},
228 {REG_A5XX_RBBM_CLOCK_HYST_RB_CCU0, 0x04040404},
229 {REG_A5XX_RBBM_CLOCK_HYST_RB_CCU1, 0x04040404},
230 {REG_A5XX_RBBM_CLOCK_HYST_RB_CCU2, 0x04040404},
231 {REG_A5XX_RBBM_CLOCK_HYST_RB_CCU3, 0x04040404},
232 {REG_A5XX_RBBM_CLOCK_HYST_RAC, 0x07444044},
233 {REG_A5XX_RBBM_CLOCK_DELAY_RB_CCU_L1_0, 0x00000002},
234 {REG_A5XX_RBBM_CLOCK_DELAY_RB_CCU_L1_1, 0x00000002},
235 {REG_A5XX_RBBM_CLOCK_DELAY_RB_CCU_L1_2, 0x00000002},
236 {REG_A5XX_RBBM_CLOCK_DELAY_RB_CCU_L1_3, 0x00000002},
237 {REG_A5XX_RBBM_CLOCK_DELAY_RAC, 0x00010011},
238 {REG_A5XX_RBBM_CLOCK_CNTL_TSE_RAS_RBBM, 0x04222222},
239 {REG_A5XX_RBBM_CLOCK_MODE_GPC, 0x02222222},
240 {REG_A5XX_RBBM_CLOCK_MODE_VFD, 0x00002222},
241 {REG_A5XX_RBBM_CLOCK_HYST_TSE_RAS_RBBM, 0x00000000},
242 {REG_A5XX_RBBM_CLOCK_HYST_GPC, 0x04104004},
243 {REG_A5XX_RBBM_CLOCK_HYST_VFD, 0x00000000},
244 {REG_A5XX_RBBM_CLOCK_DELAY_HLSQ, 0x00000000},
245 {REG_A5XX_RBBM_CLOCK_DELAY_TSE_RAS_RBBM, 0x00004000},
246 {REG_A5XX_RBBM_CLOCK_DELAY_GPC, 0x00000200},
247 {REG_A5XX_RBBM_CLOCK_DELAY_VFD, 0x00002222}
248};
249
Jordan Crouse6e749e52017-07-27 10:42:31 -0600250void a5xx_set_hwcg(struct msm_gpu *gpu, bool state)
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700251{
252 unsigned int i;
253
Jordan Crouse6e749e52017-07-27 10:42:31 -0600254 for (i = 0; i < ARRAY_SIZE(a5xx_hwcg); i++)
255 gpu_write(gpu, a5xx_hwcg[i].offset,
256 state ? a5xx_hwcg[i].value : 0);
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700257
Jordan Crouse6e749e52017-07-27 10:42:31 -0600258 gpu_write(gpu, REG_A5XX_RBBM_CLOCK_CNTL, state ? 0xAAA8AA00 : 0);
259 gpu_write(gpu, REG_A5XX_RBBM_ISDB_CNT, state ? 0x182 : 0x180);
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700260}
261
262static int a5xx_me_init(struct msm_gpu *gpu)
263{
264 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
Jordan Crousef97deca2017-10-20 11:06:57 -0600265 struct msm_ringbuffer *ring = gpu->rb[0];
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700266
267 OUT_PKT7(ring, CP_ME_INIT, 8);
268
269 OUT_RING(ring, 0x0000002F);
270
271 /* Enable multiple hardware contexts */
272 OUT_RING(ring, 0x00000003);
273
274 /* Enable error detection */
275 OUT_RING(ring, 0x20000000);
276
277 /* Don't enable header dump */
278 OUT_RING(ring, 0x00000000);
279 OUT_RING(ring, 0x00000000);
280
281 /* Specify workarounds for various microcode issues */
282 if (adreno_is_a530(adreno_gpu)) {
283 /* Workaround for token end syncs
284 * Force a WFI after every direct-render 3D mode draw and every
285 * 2D mode 3 draw
286 */
287 OUT_RING(ring, 0x0000000B);
288 } else {
289 /* No workarounds enabled */
290 OUT_RING(ring, 0x00000000);
291 }
292
293 OUT_RING(ring, 0x00000000);
294 OUT_RING(ring, 0x00000000);
295
Jordan Crousef97deca2017-10-20 11:06:57 -0600296 gpu->funcs->flush(gpu, ring);
297 return a5xx_idle(gpu, ring) ? 0 : -EINVAL;
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700298}
299
300static struct drm_gem_object *a5xx_ucode_load_bo(struct msm_gpu *gpu,
301 const struct firmware *fw, u64 *iova)
302{
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700303 struct drm_gem_object *bo;
304 void *ptr;
305
Jordan Crouse82232862017-07-27 10:42:40 -0600306 ptr = msm_gem_kernel_new_locked(gpu->dev, fw->size - 4,
307 MSM_BO_UNCACHED | MSM_BO_GPU_READONLY, gpu->aspace, &bo, iova);
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700308
Jordan Crouse82232862017-07-27 10:42:40 -0600309 if (IS_ERR(ptr))
310 return ERR_CAST(ptr);
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700311
312 memcpy(ptr, &fw->data[4], fw->size - 4);
313
Sushmita Susheelendra0e082702017-06-13 16:52:54 -0600314 msm_gem_put_vaddr(bo);
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700315 return bo;
316}
317
318static int a5xx_ucode_init(struct msm_gpu *gpu)
319{
320 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
321 struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu);
322 int ret;
323
324 if (!a5xx_gpu->pm4_bo) {
325 a5xx_gpu->pm4_bo = a5xx_ucode_load_bo(gpu, adreno_gpu->pm4,
326 &a5xx_gpu->pm4_iova);
327
328 if (IS_ERR(a5xx_gpu->pm4_bo)) {
329 ret = PTR_ERR(a5xx_gpu->pm4_bo);
330 a5xx_gpu->pm4_bo = NULL;
331 dev_err(gpu->dev->dev, "could not allocate PM4: %d\n",
332 ret);
333 return ret;
334 }
335 }
336
337 if (!a5xx_gpu->pfp_bo) {
338 a5xx_gpu->pfp_bo = a5xx_ucode_load_bo(gpu, adreno_gpu->pfp,
339 &a5xx_gpu->pfp_iova);
340
341 if (IS_ERR(a5xx_gpu->pfp_bo)) {
342 ret = PTR_ERR(a5xx_gpu->pfp_bo);
343 a5xx_gpu->pfp_bo = NULL;
344 dev_err(gpu->dev->dev, "could not allocate PFP: %d\n",
345 ret);
346 return ret;
347 }
348 }
349
350 gpu_write64(gpu, REG_A5XX_CP_ME_INSTR_BASE_LO,
351 REG_A5XX_CP_ME_INSTR_BASE_HI, a5xx_gpu->pm4_iova);
352
353 gpu_write64(gpu, REG_A5XX_CP_PFP_INSTR_BASE_LO,
354 REG_A5XX_CP_PFP_INSTR_BASE_HI, a5xx_gpu->pfp_iova);
355
356 return 0;
357}
358
Jordan Crouse7c658172017-05-17 08:45:29 -0600359#define SCM_GPU_ZAP_SHADER_RESUME 0
360
361static int a5xx_zap_shader_resume(struct msm_gpu *gpu)
362{
363 int ret;
364
365 ret = qcom_scm_set_remote_state(SCM_GPU_ZAP_SHADER_RESUME, GPU_PAS_ID);
366 if (ret)
367 DRM_ERROR("%s: zap-shader resume failed: %d\n",
368 gpu->name, ret);
369
370 return ret;
371}
372
Jordan Crouse7c658172017-05-17 08:45:29 -0600373static int a5xx_zap_shader_init(struct msm_gpu *gpu)
374{
375 static bool loaded;
376 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
Jordan Crouse8d6f0822017-07-27 10:42:33 -0600377 struct platform_device *pdev = gpu->pdev;
Jordan Crouse7c658172017-05-17 08:45:29 -0600378 int ret;
379
380 /*
381 * If the zap shader is already loaded into memory we just need to kick
382 * the remote processor to reinitialize it
383 */
384 if (loaded)
385 return a5xx_zap_shader_resume(gpu);
386
387 /* We need SCM to be able to load the firmware */
388 if (!qcom_scm_is_available()) {
389 DRM_DEV_ERROR(&pdev->dev, "SCM is not available\n");
390 return -EPROBE_DEFER;
391 }
392
393 /* Each GPU has a target specific zap shader firmware name to use */
394 if (!adreno_gpu->info->zapfw) {
395 DRM_DEV_ERROR(&pdev->dev,
396 "Zap shader firmware file not specified for this target\n");
397 return -ENODEV;
398 }
399
Rob Clarke8f3de92017-10-16 10:13:15 -0400400 ret = zap_shader_load_mdt(gpu, adreno_gpu->info->zapfw);
Jordan Crouse7c658172017-05-17 08:45:29 -0600401
402 loaded = !ret;
403
404 return ret;
405}
406
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700407#define A5XX_INT_MASK (A5XX_RBBM_INT_0_MASK_RBBM_AHB_ERROR | \
408 A5XX_RBBM_INT_0_MASK_RBBM_TRANSFER_TIMEOUT | \
409 A5XX_RBBM_INT_0_MASK_RBBM_ME_MS_TIMEOUT | \
410 A5XX_RBBM_INT_0_MASK_RBBM_PFP_MS_TIMEOUT | \
411 A5XX_RBBM_INT_0_MASK_RBBM_ETS_MS_TIMEOUT | \
412 A5XX_RBBM_INT_0_MASK_RBBM_ATB_ASYNC_OVERFLOW | \
413 A5XX_RBBM_INT_0_MASK_CP_HW_ERROR | \
Jordan Crouseac1b5ab2017-07-27 10:42:36 -0600414 A5XX_RBBM_INT_0_MASK_MISC_HANG_DETECT | \
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700415 A5XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS | \
416 A5XX_RBBM_INT_0_MASK_UCHE_OOB_ACCESS | \
417 A5XX_RBBM_INT_0_MASK_GPMU_VOLTAGE_DROOP)
418
419static int a5xx_hw_init(struct msm_gpu *gpu)
420{
421 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
422 int ret;
423
424 gpu_write(gpu, REG_A5XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x00000003);
425
426 /* Make all blocks contribute to the GPU BUSY perf counter */
427 gpu_write(gpu, REG_A5XX_RBBM_PERFCTR_GPU_BUSY_MASKED, 0xFFFFFFFF);
428
429 /* Enable RBBM error reporting bits */
430 gpu_write(gpu, REG_A5XX_RBBM_AHB_CNTL0, 0x00000001);
431
Rob Clark4e09b952017-01-30 11:15:14 -0500432 if (adreno_gpu->info->quirks & ADRENO_QUIRK_FAULT_DETECT_MASK) {
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700433 /*
434 * Mask out the activity signals from RB1-3 to avoid false
435 * positives
436 */
437
438 gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL11,
439 0xF0000000);
440 gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL12,
441 0xFFFFFFFF);
442 gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL13,
443 0xFFFFFFFF);
444 gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL14,
445 0xFFFFFFFF);
446 gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL15,
447 0xFFFFFFFF);
448 gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL16,
449 0xFFFFFFFF);
450 gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL17,
451 0xFFFFFFFF);
452 gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL18,
453 0xFFFFFFFF);
454 }
455
456 /* Enable fault detection */
457 gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_INT_CNTL,
458 (1 << 30) | 0xFFFF);
459
460 /* Turn on performance counters */
461 gpu_write(gpu, REG_A5XX_RBBM_PERFCTR_CNTL, 0x01);
462
463 /* Increase VFD cache access so LRZ and other data gets evicted less */
464 gpu_write(gpu, REG_A5XX_UCHE_CACHE_WAYS, 0x02);
465
466 /* Disable L2 bypass in the UCHE */
467 gpu_write(gpu, REG_A5XX_UCHE_TRAP_BASE_LO, 0xFFFF0000);
468 gpu_write(gpu, REG_A5XX_UCHE_TRAP_BASE_HI, 0x0001FFFF);
469 gpu_write(gpu, REG_A5XX_UCHE_WRITE_THRU_BASE_LO, 0xFFFF0000);
470 gpu_write(gpu, REG_A5XX_UCHE_WRITE_THRU_BASE_HI, 0x0001FFFF);
471
472 /* Set the GMEM VA range (0 to gpu->gmem) */
473 gpu_write(gpu, REG_A5XX_UCHE_GMEM_RANGE_MIN_LO, 0x00100000);
474 gpu_write(gpu, REG_A5XX_UCHE_GMEM_RANGE_MIN_HI, 0x00000000);
475 gpu_write(gpu, REG_A5XX_UCHE_GMEM_RANGE_MAX_LO,
476 0x00100000 + adreno_gpu->gmem - 1);
477 gpu_write(gpu, REG_A5XX_UCHE_GMEM_RANGE_MAX_HI, 0x00000000);
478
479 gpu_write(gpu, REG_A5XX_CP_MEQ_THRESHOLDS, 0x40);
480 gpu_write(gpu, REG_A5XX_CP_MERCIU_SIZE, 0x40);
481 gpu_write(gpu, REG_A5XX_CP_ROQ_THRESHOLDS_2, 0x80000060);
482 gpu_write(gpu, REG_A5XX_CP_ROQ_THRESHOLDS_1, 0x40201B16);
483
484 gpu_write(gpu, REG_A5XX_PC_DBG_ECO_CNTL, (0x400 << 11 | 0x300 << 22));
485
Rob Clark4e09b952017-01-30 11:15:14 -0500486 if (adreno_gpu->info->quirks & ADRENO_QUIRK_TWO_PASS_USE_WFI)
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700487 gpu_rmw(gpu, REG_A5XX_PC_DBG_ECO_CNTL, 0, (1 << 8));
488
489 gpu_write(gpu, REG_A5XX_PC_DBG_ECO_CNTL, 0xc0200100);
490
491 /* Enable USE_RETENTION_FLOPS */
492 gpu_write(gpu, REG_A5XX_CP_CHICKEN_DBG, 0x02000000);
493
494 /* Enable ME/PFP split notification */
495 gpu_write(gpu, REG_A5XX_RBBM_AHB_CNTL1, 0xA6FFFFFF);
496
497 /* Enable HWCG */
Jordan Crouse6e749e52017-07-27 10:42:31 -0600498 a5xx_set_hwcg(gpu, true);
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700499
500 gpu_write(gpu, REG_A5XX_RBBM_AHB_CNTL2, 0x0000003F);
501
502 /* Set the highest bank bit */
503 gpu_write(gpu, REG_A5XX_TPL1_MODE_CNTL, 2 << 7);
504 gpu_write(gpu, REG_A5XX_RB_MODE_CNTL, 2 << 1);
505
506 /* Protect registers from the CP */
507 gpu_write(gpu, REG_A5XX_CP_PROTECT_CNTL, 0x00000007);
508
509 /* RBBM */
510 gpu_write(gpu, REG_A5XX_CP_PROTECT(0), ADRENO_PROTECT_RW(0x04, 4));
511 gpu_write(gpu, REG_A5XX_CP_PROTECT(1), ADRENO_PROTECT_RW(0x08, 8));
512 gpu_write(gpu, REG_A5XX_CP_PROTECT(2), ADRENO_PROTECT_RW(0x10, 16));
513 gpu_write(gpu, REG_A5XX_CP_PROTECT(3), ADRENO_PROTECT_RW(0x20, 32));
514 gpu_write(gpu, REG_A5XX_CP_PROTECT(4), ADRENO_PROTECT_RW(0x40, 64));
515 gpu_write(gpu, REG_A5XX_CP_PROTECT(5), ADRENO_PROTECT_RW(0x80, 64));
516
517 /* Content protect */
518 gpu_write(gpu, REG_A5XX_CP_PROTECT(6),
519 ADRENO_PROTECT_RW(REG_A5XX_RBBM_SECVID_TSB_TRUSTED_BASE_LO,
520 16));
521 gpu_write(gpu, REG_A5XX_CP_PROTECT(7),
522 ADRENO_PROTECT_RW(REG_A5XX_RBBM_SECVID_TRUST_CNTL, 2));
523
524 /* CP */
525 gpu_write(gpu, REG_A5XX_CP_PROTECT(8), ADRENO_PROTECT_RW(0x800, 64));
526 gpu_write(gpu, REG_A5XX_CP_PROTECT(9), ADRENO_PROTECT_RW(0x840, 8));
527 gpu_write(gpu, REG_A5XX_CP_PROTECT(10), ADRENO_PROTECT_RW(0x880, 32));
528 gpu_write(gpu, REG_A5XX_CP_PROTECT(11), ADRENO_PROTECT_RW(0xAA0, 1));
529
530 /* RB */
531 gpu_write(gpu, REG_A5XX_CP_PROTECT(12), ADRENO_PROTECT_RW(0xCC0, 1));
532 gpu_write(gpu, REG_A5XX_CP_PROTECT(13), ADRENO_PROTECT_RW(0xCF0, 2));
533
534 /* VPC */
535 gpu_write(gpu, REG_A5XX_CP_PROTECT(14), ADRENO_PROTECT_RW(0xE68, 8));
536 gpu_write(gpu, REG_A5XX_CP_PROTECT(15), ADRENO_PROTECT_RW(0xE70, 4));
537
538 /* UCHE */
539 gpu_write(gpu, REG_A5XX_CP_PROTECT(16), ADRENO_PROTECT_RW(0xE80, 16));
540
541 if (adreno_is_a530(adreno_gpu))
542 gpu_write(gpu, REG_A5XX_CP_PROTECT(17),
543 ADRENO_PROTECT_RW(0x10000, 0x8000));
544
545 gpu_write(gpu, REG_A5XX_RBBM_SECVID_TSB_CNTL, 0);
546 /*
547 * Disable the trusted memory range - we don't actually supported secure
548 * memory rendering at this point in time and we don't want to block off
549 * part of the virtual memory space.
550 */
551 gpu_write64(gpu, REG_A5XX_RBBM_SECVID_TSB_TRUSTED_BASE_LO,
552 REG_A5XX_RBBM_SECVID_TSB_TRUSTED_BASE_HI, 0x00000000);
553 gpu_write(gpu, REG_A5XX_RBBM_SECVID_TSB_TRUSTED_SIZE, 0x00000000);
554
555 ret = adreno_hw_init(gpu);
556 if (ret)
557 return ret;
558
Rob Clarkeec874c2017-10-16 09:22:38 -0400559 a5xx_gpmu_ucode_init(gpu);
560
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700561 ret = a5xx_ucode_init(gpu);
562 if (ret)
563 return ret;
564
565 /* Disable the interrupts through the initial bringup stage */
566 gpu_write(gpu, REG_A5XX_RBBM_INT_0_MASK, A5XX_INT_MASK);
567
568 /* Clear ME_HALT to start the micro engine */
569 gpu_write(gpu, REG_A5XX_CP_PFP_ME_CNTL, 0);
570 ret = a5xx_me_init(gpu);
571 if (ret)
572 return ret;
573
Jordan Crouse2401a002016-11-28 12:28:34 -0700574 ret = a5xx_power_init(gpu);
575 if (ret)
576 return ret;
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700577
578 /*
579 * Send a pipeline event stat to get misbehaving counters to start
580 * ticking correctly
581 */
582 if (adreno_is_a530(adreno_gpu)) {
Jordan Crousef97deca2017-10-20 11:06:57 -0600583 OUT_PKT7(gpu->rb[0], CP_EVENT_WRITE, 1);
584 OUT_RING(gpu->rb[0], 0x0F);
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700585
Jordan Crousef97deca2017-10-20 11:06:57 -0600586 gpu->funcs->flush(gpu, gpu->rb[0]);
587 if (!a5xx_idle(gpu, gpu->rb[0]))
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700588 return -EINVAL;
589 }
590
Jordan Crouse7c658172017-05-17 08:45:29 -0600591 /*
592 * Try to load a zap shader into the secure world. If successful
593 * we can use the CP to switch out of secure mode. If not then we
594 * have no resource but to try to switch ourselves out manually. If we
595 * guessed wrong then access to the RBBM_SECVID_TRUST_CNTL register will
596 * be blocked and a permissions violation will soon follow.
597 */
598 ret = a5xx_zap_shader_init(gpu);
599 if (!ret) {
Jordan Crousef97deca2017-10-20 11:06:57 -0600600 OUT_PKT7(gpu->rb[0], CP_SET_SECURE_MODE, 1);
601 OUT_RING(gpu->rb[0], 0x00000000);
Jordan Crouse7c658172017-05-17 08:45:29 -0600602
Jordan Crousef97deca2017-10-20 11:06:57 -0600603 gpu->funcs->flush(gpu, gpu->rb[0]);
604 if (!a5xx_idle(gpu, gpu->rb[0]))
Jordan Crouse7c658172017-05-17 08:45:29 -0600605 return -EINVAL;
606 } else {
607 /* Print a warning so if we die, we know why */
608 dev_warn_once(gpu->dev->dev,
609 "Zap shader not enabled - using SECVID_TRUST_CNTL instead\n");
610 gpu_write(gpu, REG_A5XX_RBBM_SECVID_TRUST_CNTL, 0x0);
611 }
Jordan Crouse2401a002016-11-28 12:28:34 -0700612
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700613 return 0;
614}
615
616static void a5xx_recover(struct msm_gpu *gpu)
617{
618 int i;
619
620 adreno_dump_info(gpu);
621
622 for (i = 0; i < 8; i++) {
623 printk("CP_SCRATCH_REG%d: %u\n", i,
624 gpu_read(gpu, REG_A5XX_CP_SCRATCH_REG(i)));
625 }
626
627 if (hang_debug)
628 a5xx_dump(gpu);
629
630 gpu_write(gpu, REG_A5XX_RBBM_SW_RESET_CMD, 1);
631 gpu_read(gpu, REG_A5XX_RBBM_SW_RESET_CMD);
632 gpu_write(gpu, REG_A5XX_RBBM_SW_RESET_CMD, 0);
633 adreno_recover(gpu);
634}
635
636static void a5xx_destroy(struct msm_gpu *gpu)
637{
638 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
639 struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu);
640
641 DBG("%s", gpu->name);
642
643 if (a5xx_gpu->pm4_bo) {
644 if (a5xx_gpu->pm4_iova)
Rob Clark8bdcd942017-06-13 11:07:08 -0400645 msm_gem_put_iova(a5xx_gpu->pm4_bo, gpu->aspace);
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700646 drm_gem_object_unreference_unlocked(a5xx_gpu->pm4_bo);
647 }
648
649 if (a5xx_gpu->pfp_bo) {
650 if (a5xx_gpu->pfp_iova)
Rob Clark8bdcd942017-06-13 11:07:08 -0400651 msm_gem_put_iova(a5xx_gpu->pfp_bo, gpu->aspace);
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700652 drm_gem_object_unreference_unlocked(a5xx_gpu->pfp_bo);
653 }
654
Jordan Crouse2401a002016-11-28 12:28:34 -0700655 if (a5xx_gpu->gpmu_bo) {
Jordan Crouse2002c9c2017-03-07 09:50:27 -0700656 if (a5xx_gpu->gpmu_iova)
Rob Clark8bdcd942017-06-13 11:07:08 -0400657 msm_gem_put_iova(a5xx_gpu->gpmu_bo, gpu->aspace);
Jordan Crouse2401a002016-11-28 12:28:34 -0700658 drm_gem_object_unreference_unlocked(a5xx_gpu->gpmu_bo);
659 }
660
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700661 adreno_gpu_cleanup(adreno_gpu);
662 kfree(a5xx_gpu);
663}
664
665static inline bool _a5xx_check_idle(struct msm_gpu *gpu)
666{
667 if (gpu_read(gpu, REG_A5XX_RBBM_STATUS) & ~A5XX_RBBM_STATUS_HI_BUSY)
668 return false;
669
670 /*
671 * Nearly every abnormality ends up pausing the GPU and triggering a
672 * fault so we can safely just watch for this one interrupt to fire
673 */
674 return !(gpu_read(gpu, REG_A5XX_RBBM_INT_0_STATUS) &
675 A5XX_RBBM_INT_0_MASK_MISC_HANG_DETECT);
676}
677
Jordan Crousef97deca2017-10-20 11:06:57 -0600678bool a5xx_idle(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700679{
680 /* wait for CP to drain ringbuffer: */
Jordan Crousef97deca2017-10-20 11:06:57 -0600681 if (!adreno_idle(gpu, ring))
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700682 return false;
683
684 if (spin_until(_a5xx_check_idle(gpu))) {
Jordan Crousef97deca2017-10-20 11:06:57 -0600685 DRM_ERROR("%s: %ps: timeout waiting for GPU to idle: status %8.8X irq %8.8X rptr/wptr %d/%d\n",
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700686 gpu->name, __builtin_return_address(0),
687 gpu_read(gpu, REG_A5XX_RBBM_STATUS),
Jordan Crousef97deca2017-10-20 11:06:57 -0600688 gpu_read(gpu, REG_A5XX_RBBM_INT_0_STATUS),
689 gpu_read(gpu, REG_A5XX_CP_RB_RPTR),
690 gpu_read(gpu, REG_A5XX_CP_RB_WPTR));
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700691 return false;
692 }
693
694 return true;
695}
696
Rob Clark7f8036b2016-12-07 11:13:53 -0500697static int a5xx_fault_handler(void *arg, unsigned long iova, int flags)
698{
699 struct msm_gpu *gpu = arg;
700 pr_warn_ratelimited("*** gpu fault: iova=%08lx, flags=%d (%u,%u,%u,%u)\n",
701 iova, flags,
702 gpu_read(gpu, REG_A5XX_CP_SCRATCH_REG(4)),
703 gpu_read(gpu, REG_A5XX_CP_SCRATCH_REG(5)),
704 gpu_read(gpu, REG_A5XX_CP_SCRATCH_REG(6)),
705 gpu_read(gpu, REG_A5XX_CP_SCRATCH_REG(7)));
706
707 return -EFAULT;
708}
709
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700710static void a5xx_cp_err_irq(struct msm_gpu *gpu)
711{
712 u32 status = gpu_read(gpu, REG_A5XX_CP_INTERRUPT_STATUS);
713
714 if (status & A5XX_CP_INT_CP_OPCODE_ERROR) {
715 u32 val;
716
717 gpu_write(gpu, REG_A5XX_CP_PFP_STAT_ADDR, 0);
718
719 /*
720 * REG_A5XX_CP_PFP_STAT_DATA is indexed, and we want index 1 so
721 * read it twice
722 */
723
724 gpu_read(gpu, REG_A5XX_CP_PFP_STAT_DATA);
725 val = gpu_read(gpu, REG_A5XX_CP_PFP_STAT_DATA);
726
727 dev_err_ratelimited(gpu->dev->dev, "CP | opcode error | possible opcode=0x%8.8X\n",
728 val);
729 }
730
731 if (status & A5XX_CP_INT_CP_HW_FAULT_ERROR)
732 dev_err_ratelimited(gpu->dev->dev, "CP | HW fault | status=0x%8.8X\n",
733 gpu_read(gpu, REG_A5XX_CP_HW_FAULT));
734
735 if (status & A5XX_CP_INT_CP_DMA_ERROR)
736 dev_err_ratelimited(gpu->dev->dev, "CP | DMA error\n");
737
738 if (status & A5XX_CP_INT_CP_REGISTER_PROTECTION_ERROR) {
739 u32 val = gpu_read(gpu, REG_A5XX_CP_PROTECT_STATUS);
740
741 dev_err_ratelimited(gpu->dev->dev,
742 "CP | protected mode error | %s | addr=0x%8.8X | status=0x%8.8X\n",
743 val & (1 << 24) ? "WRITE" : "READ",
744 (val & 0xFFFFF) >> 2, val);
745 }
746
747 if (status & A5XX_CP_INT_CP_AHB_ERROR) {
748 u32 status = gpu_read(gpu, REG_A5XX_CP_AHB_FAULT);
749 const char *access[16] = { "reserved", "reserved",
750 "timestamp lo", "timestamp hi", "pfp read", "pfp write",
751 "", "", "me read", "me write", "", "", "crashdump read",
752 "crashdump write" };
753
754 dev_err_ratelimited(gpu->dev->dev,
755 "CP | AHB error | addr=%X access=%s error=%d | status=0x%8.8X\n",
756 status & 0xFFFFF, access[(status >> 24) & 0xF],
757 (status & (1 << 31)), status);
758 }
759}
760
Jordan Crouse7352fb52017-03-07 09:50:29 -0700761static void a5xx_rbbm_err_irq(struct msm_gpu *gpu, u32 status)
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700762{
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700763 if (status & A5XX_RBBM_INT_0_MASK_RBBM_AHB_ERROR) {
764 u32 val = gpu_read(gpu, REG_A5XX_RBBM_AHB_ERROR_STATUS);
765
766 dev_err_ratelimited(gpu->dev->dev,
767 "RBBM | AHB bus error | %s | addr=0x%X | ports=0x%X:0x%X\n",
768 val & (1 << 28) ? "WRITE" : "READ",
769 (val & 0xFFFFF) >> 2, (val >> 20) & 0x3,
770 (val >> 24) & 0xF);
771
772 /* Clear the error */
773 gpu_write(gpu, REG_A5XX_RBBM_AHB_CMD, (1 << 4));
Jordan Crouse7352fb52017-03-07 09:50:29 -0700774
775 /* Clear the interrupt */
776 gpu_write(gpu, REG_A5XX_RBBM_INT_CLEAR_CMD,
777 A5XX_RBBM_INT_0_MASK_RBBM_AHB_ERROR);
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700778 }
779
780 if (status & A5XX_RBBM_INT_0_MASK_RBBM_TRANSFER_TIMEOUT)
781 dev_err_ratelimited(gpu->dev->dev, "RBBM | AHB transfer timeout\n");
782
783 if (status & A5XX_RBBM_INT_0_MASK_RBBM_ME_MS_TIMEOUT)
784 dev_err_ratelimited(gpu->dev->dev, "RBBM | ME master split | status=0x%X\n",
785 gpu_read(gpu, REG_A5XX_RBBM_AHB_ME_SPLIT_STATUS));
786
787 if (status & A5XX_RBBM_INT_0_MASK_RBBM_PFP_MS_TIMEOUT)
788 dev_err_ratelimited(gpu->dev->dev, "RBBM | PFP master split | status=0x%X\n",
789 gpu_read(gpu, REG_A5XX_RBBM_AHB_PFP_SPLIT_STATUS));
790
791 if (status & A5XX_RBBM_INT_0_MASK_RBBM_ETS_MS_TIMEOUT)
792 dev_err_ratelimited(gpu->dev->dev, "RBBM | ETS master split | status=0x%X\n",
793 gpu_read(gpu, REG_A5XX_RBBM_AHB_ETS_SPLIT_STATUS));
794
795 if (status & A5XX_RBBM_INT_0_MASK_RBBM_ATB_ASYNC_OVERFLOW)
796 dev_err_ratelimited(gpu->dev->dev, "RBBM | ATB ASYNC overflow\n");
797
798 if (status & A5XX_RBBM_INT_0_MASK_RBBM_ATB_BUS_OVERFLOW)
799 dev_err_ratelimited(gpu->dev->dev, "RBBM | ATB bus overflow\n");
800}
801
802static void a5xx_uche_err_irq(struct msm_gpu *gpu)
803{
804 uint64_t addr = (uint64_t) gpu_read(gpu, REG_A5XX_UCHE_TRAP_LOG_HI);
805
806 addr |= gpu_read(gpu, REG_A5XX_UCHE_TRAP_LOG_LO);
807
808 dev_err_ratelimited(gpu->dev->dev, "UCHE | Out of bounds access | addr=0x%llX\n",
809 addr);
810}
811
812static void a5xx_gpmu_err_irq(struct msm_gpu *gpu)
813{
814 dev_err_ratelimited(gpu->dev->dev, "GPMU | voltage droop\n");
815}
816
Jordan Crouseac1b5ab2017-07-27 10:42:36 -0600817static void a5xx_fault_detect_irq(struct msm_gpu *gpu)
818{
819 struct drm_device *dev = gpu->dev;
820 struct msm_drm_private *priv = dev->dev_private;
Jordan Crousef97deca2017-10-20 11:06:57 -0600821 struct msm_ringbuffer *ring = gpu->funcs->active_ring(gpu);
Jordan Crouseac1b5ab2017-07-27 10:42:36 -0600822
Jordan Crousef97deca2017-10-20 11:06:57 -0600823 dev_err(dev->dev, "gpu fault ring %d fence %x status %8.8X rb %4.4x/%4.4x ib1 %16.16llX/%4.4x ib2 %16.16llX/%4.4x\n",
824 ring ? ring->id : -1, ring ? ring->seqno : 0,
Jordan Crouseac1b5ab2017-07-27 10:42:36 -0600825 gpu_read(gpu, REG_A5XX_RBBM_STATUS),
826 gpu_read(gpu, REG_A5XX_CP_RB_RPTR),
827 gpu_read(gpu, REG_A5XX_CP_RB_WPTR),
828 gpu_read64(gpu, REG_A5XX_CP_IB1_BASE, REG_A5XX_CP_IB1_BASE_HI),
829 gpu_read(gpu, REG_A5XX_CP_IB1_BUFSZ),
830 gpu_read64(gpu, REG_A5XX_CP_IB2_BASE, REG_A5XX_CP_IB2_BASE_HI),
831 gpu_read(gpu, REG_A5XX_CP_IB2_BUFSZ));
832
833 /* Turn off the hangcheck timer to keep it from bothering us */
834 del_timer(&gpu->hangcheck_timer);
835
836 queue_work(priv->wq, &gpu->recover_work);
837}
838
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700839#define RBBM_ERROR_MASK \
840 (A5XX_RBBM_INT_0_MASK_RBBM_AHB_ERROR | \
841 A5XX_RBBM_INT_0_MASK_RBBM_TRANSFER_TIMEOUT | \
842 A5XX_RBBM_INT_0_MASK_RBBM_ME_MS_TIMEOUT | \
843 A5XX_RBBM_INT_0_MASK_RBBM_PFP_MS_TIMEOUT | \
844 A5XX_RBBM_INT_0_MASK_RBBM_ETS_MS_TIMEOUT | \
845 A5XX_RBBM_INT_0_MASK_RBBM_ATB_ASYNC_OVERFLOW)
846
847static irqreturn_t a5xx_irq(struct msm_gpu *gpu)
848{
849 u32 status = gpu_read(gpu, REG_A5XX_RBBM_INT_0_STATUS);
850
Jordan Crouse7352fb52017-03-07 09:50:29 -0700851 /*
852 * Clear all the interrupts except RBBM_AHB_ERROR - if we clear it
853 * before the source is cleared the interrupt will storm.
854 */
855 gpu_write(gpu, REG_A5XX_RBBM_INT_CLEAR_CMD,
856 status & ~A5XX_RBBM_INT_0_MASK_RBBM_AHB_ERROR);
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700857
Jordan Crouse7352fb52017-03-07 09:50:29 -0700858 /* Pass status to a5xx_rbbm_err_irq because we've already cleared it */
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700859 if (status & RBBM_ERROR_MASK)
Jordan Crouse7352fb52017-03-07 09:50:29 -0700860 a5xx_rbbm_err_irq(gpu, status);
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700861
862 if (status & A5XX_RBBM_INT_0_MASK_CP_HW_ERROR)
863 a5xx_cp_err_irq(gpu);
864
Jordan Crouseac1b5ab2017-07-27 10:42:36 -0600865 if (status & A5XX_RBBM_INT_0_MASK_MISC_HANG_DETECT)
866 a5xx_fault_detect_irq(gpu);
867
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700868 if (status & A5XX_RBBM_INT_0_MASK_UCHE_OOB_ACCESS)
869 a5xx_uche_err_irq(gpu);
870
871 if (status & A5XX_RBBM_INT_0_MASK_GPMU_VOLTAGE_DROOP)
872 a5xx_gpmu_err_irq(gpu);
873
874 if (status & A5XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS)
875 msm_gpu_retire(gpu);
876
877 return IRQ_HANDLED;
878}
879
880static const u32 a5xx_register_offsets[REG_ADRENO_REGISTER_MAX] = {
881 REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_BASE, REG_A5XX_CP_RB_BASE),
882 REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_BASE_HI, REG_A5XX_CP_RB_BASE_HI),
883 REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_RPTR_ADDR, REG_A5XX_CP_RB_RPTR_ADDR),
884 REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_RPTR_ADDR_HI,
885 REG_A5XX_CP_RB_RPTR_ADDR_HI),
886 REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_RPTR, REG_A5XX_CP_RB_RPTR),
887 REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_WPTR, REG_A5XX_CP_RB_WPTR),
888 REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_CNTL, REG_A5XX_CP_RB_CNTL),
889};
890
891static const u32 a5xx_registers[] = {
892 0x0000, 0x0002, 0x0004, 0x0020, 0x0022, 0x0026, 0x0029, 0x002B,
893 0x002E, 0x0035, 0x0038, 0x0042, 0x0044, 0x0044, 0x0047, 0x0095,
894 0x0097, 0x00BB, 0x03A0, 0x0464, 0x0469, 0x046F, 0x04D2, 0x04D3,
Jordan Crouse3394f562017-07-27 10:42:30 -0600895 0x04E0, 0x0533, 0x0540, 0x0555, 0x0800, 0x081A, 0x081F, 0x0841,
896 0x0860, 0x0860, 0x0880, 0x08A0, 0x0B00, 0x0B12, 0x0B15, 0x0B28,
897 0x0B78, 0x0B7F, 0x0BB0, 0x0BBD, 0x0BC0, 0x0BC6, 0x0BD0, 0x0C53,
898 0x0C60, 0x0C61, 0x0C80, 0x0C82, 0x0C84, 0x0C85, 0x0C90, 0x0C98,
899 0x0CA0, 0x0CA0, 0x0CB0, 0x0CB2, 0x2180, 0x2185, 0x2580, 0x2585,
900 0x0CC1, 0x0CC1, 0x0CC4, 0x0CC7, 0x0CCC, 0x0CCC, 0x0CD0, 0x0CD8,
901 0x0CE0, 0x0CE5, 0x0CE8, 0x0CE8, 0x0CEC, 0x0CF1, 0x0CFB, 0x0D0E,
902 0x2100, 0x211E, 0x2140, 0x2145, 0x2500, 0x251E, 0x2540, 0x2545,
903 0x0D10, 0x0D17, 0x0D20, 0x0D23, 0x0D30, 0x0D30, 0x20C0, 0x20C0,
904 0x24C0, 0x24C0, 0x0E40, 0x0E43, 0x0E4A, 0x0E4A, 0x0E50, 0x0E57,
905 0x0E60, 0x0E7C, 0x0E80, 0x0E8E, 0x0E90, 0x0E96, 0x0EA0, 0x0EA8,
906 0x0EB0, 0x0EB2, 0xE140, 0xE147, 0xE150, 0xE187, 0xE1A0, 0xE1A9,
907 0xE1B0, 0xE1B6, 0xE1C0, 0xE1C7, 0xE1D0, 0xE1D1, 0xE200, 0xE201,
908 0xE210, 0xE21C, 0xE240, 0xE268, 0xE000, 0xE006, 0xE010, 0xE09A,
909 0xE0A0, 0xE0A4, 0xE0AA, 0xE0EB, 0xE100, 0xE105, 0xE380, 0xE38F,
910 0xE3B0, 0xE3B0, 0xE400, 0xE405, 0xE408, 0xE4E9, 0xE4F0, 0xE4F0,
911 0xE280, 0xE280, 0xE282, 0xE2A3, 0xE2A5, 0xE2C2, 0xE940, 0xE947,
912 0xE950, 0xE987, 0xE9A0, 0xE9A9, 0xE9B0, 0xE9B6, 0xE9C0, 0xE9C7,
913 0xE9D0, 0xE9D1, 0xEA00, 0xEA01, 0xEA10, 0xEA1C, 0xEA40, 0xEA68,
914 0xE800, 0xE806, 0xE810, 0xE89A, 0xE8A0, 0xE8A4, 0xE8AA, 0xE8EB,
915 0xE900, 0xE905, 0xEB80, 0xEB8F, 0xEBB0, 0xEBB0, 0xEC00, 0xEC05,
916 0xEC08, 0xECE9, 0xECF0, 0xECF0, 0xEA80, 0xEA80, 0xEA82, 0xEAA3,
917 0xEAA5, 0xEAC2, 0xA800, 0xA8FF, 0xAC60, 0xAC60, 0xB000, 0xB97F,
918 0xB9A0, 0xB9BF, ~0
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700919};
920
921static void a5xx_dump(struct msm_gpu *gpu)
922{
923 dev_info(gpu->dev->dev, "status: %08x\n",
924 gpu_read(gpu, REG_A5XX_RBBM_STATUS));
925 adreno_dump(gpu);
926}
927
928static int a5xx_pm_resume(struct msm_gpu *gpu)
929{
Jordan Crouse2401a002016-11-28 12:28:34 -0700930 int ret;
931
932 /* Turn on the core power */
933 ret = msm_gpu_pm_resume(gpu);
934 if (ret)
935 return ret;
936
937 /* Turn the RBCCU domain first to limit the chances of voltage droop */
938 gpu_write(gpu, REG_A5XX_GPMU_RBCCU_POWER_CNTL, 0x778000);
939
940 /* Wait 3 usecs before polling */
941 udelay(3);
942
943 ret = spin_usecs(gpu, 20, REG_A5XX_GPMU_RBCCU_PWR_CLK_STATUS,
944 (1 << 20), (1 << 20));
945 if (ret) {
946 DRM_ERROR("%s: timeout waiting for RBCCU GDSC enable: %X\n",
947 gpu->name,
948 gpu_read(gpu, REG_A5XX_GPMU_RBCCU_PWR_CLK_STATUS));
949 return ret;
950 }
951
952 /* Turn on the SP domain */
953 gpu_write(gpu, REG_A5XX_GPMU_SP_POWER_CNTL, 0x778000);
954 ret = spin_usecs(gpu, 20, REG_A5XX_GPMU_SP_PWR_CLK_STATUS,
955 (1 << 20), (1 << 20));
956 if (ret)
957 DRM_ERROR("%s: timeout waiting for SP GDSC enable\n",
958 gpu->name);
959
960 return ret;
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700961}
962
963static int a5xx_pm_suspend(struct msm_gpu *gpu)
964{
Jordan Crouse2401a002016-11-28 12:28:34 -0700965 /* Clear the VBIF pipe before shutting down */
966 gpu_write(gpu, REG_A5XX_VBIF_XIN_HALT_CTRL0, 0xF);
967 spin_until((gpu_read(gpu, REG_A5XX_VBIF_XIN_HALT_CTRL1) & 0xF) == 0xF);
968
969 gpu_write(gpu, REG_A5XX_VBIF_XIN_HALT_CTRL0, 0);
970
971 /*
972 * Reset the VBIF before power collapse to avoid issue with FIFO
973 * entries
974 */
975 gpu_write(gpu, REG_A5XX_RBBM_BLOCK_SW_RESET_CMD, 0x003C0000);
976 gpu_write(gpu, REG_A5XX_RBBM_BLOCK_SW_RESET_CMD, 0x00000000);
977
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700978 return msm_gpu_pm_suspend(gpu);
979}
980
981static int a5xx_get_timestamp(struct msm_gpu *gpu, uint64_t *value)
982{
983 *value = gpu_read64(gpu, REG_A5XX_RBBM_PERFCTR_CP_0_LO,
984 REG_A5XX_RBBM_PERFCTR_CP_0_HI);
985
986 return 0;
987}
988
989#ifdef CONFIG_DEBUG_FS
990static void a5xx_show(struct msm_gpu *gpu, struct seq_file *m)
991{
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700992 seq_printf(m, "status: %08x\n",
993 gpu_read(gpu, REG_A5XX_RBBM_STATUS));
Jordan Crousea23cb3b2017-07-27 10:42:32 -0600994
995 /*
996 * Temporarily disable hardware clock gating before going into
997 * adreno_show to avoid issues while reading the registers
998 */
999 a5xx_set_hwcg(gpu, false);
Jordan Crouseb5f103a2016-11-28 12:28:33 -07001000 adreno_show(gpu, m);
Jordan Crousea23cb3b2017-07-27 10:42:32 -06001001 a5xx_set_hwcg(gpu, true);
Jordan Crouseb5f103a2016-11-28 12:28:33 -07001002}
1003#endif
1004
1005static const struct adreno_gpu_funcs funcs = {
1006 .base = {
1007 .get_param = adreno_get_param,
1008 .hw_init = a5xx_hw_init,
1009 .pm_suspend = a5xx_pm_suspend,
1010 .pm_resume = a5xx_pm_resume,
1011 .recover = a5xx_recover,
Jordan Crouseb5f103a2016-11-28 12:28:33 -07001012 .submit = a5xx_submit,
1013 .flush = adreno_flush,
Jordan Crousef97deca2017-10-20 11:06:57 -06001014 .active_ring = adreno_active_ring,
Jordan Crouseb5f103a2016-11-28 12:28:33 -07001015 .irq = a5xx_irq,
1016 .destroy = a5xx_destroy,
Arnd Bergmann0c3eaf12017-03-13 17:43:48 +01001017#ifdef CONFIG_DEBUG_FS
Jordan Crouseb5f103a2016-11-28 12:28:33 -07001018 .show = a5xx_show,
Arnd Bergmann0c3eaf12017-03-13 17:43:48 +01001019#endif
Jordan Crouseb5f103a2016-11-28 12:28:33 -07001020 },
1021 .get_timestamp = a5xx_get_timestamp,
1022};
1023
1024struct msm_gpu *a5xx_gpu_init(struct drm_device *dev)
1025{
1026 struct msm_drm_private *priv = dev->dev_private;
1027 struct platform_device *pdev = priv->gpu_pdev;
1028 struct a5xx_gpu *a5xx_gpu = NULL;
1029 struct adreno_gpu *adreno_gpu;
1030 struct msm_gpu *gpu;
1031 int ret;
1032
1033 if (!pdev) {
1034 dev_err(dev->dev, "No A5XX device is defined\n");
1035 return ERR_PTR(-ENXIO);
1036 }
1037
1038 a5xx_gpu = kzalloc(sizeof(*a5xx_gpu), GFP_KERNEL);
1039 if (!a5xx_gpu)
1040 return ERR_PTR(-ENOMEM);
1041
1042 adreno_gpu = &a5xx_gpu->base;
1043 gpu = &adreno_gpu->base;
1044
Jordan Crouseb5f103a2016-11-28 12:28:33 -07001045 adreno_gpu->registers = a5xx_registers;
1046 adreno_gpu->reg_offsets = a5xx_register_offsets;
1047
Jordan Crouse2401a002016-11-28 12:28:34 -07001048 a5xx_gpu->lm_leakage = 0x4E001A;
1049
Jordan Crousef97deca2017-10-20 11:06:57 -06001050 ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 1);
Jordan Crouseb5f103a2016-11-28 12:28:33 -07001051 if (ret) {
1052 a5xx_destroy(&(a5xx_gpu->base.base));
1053 return ERR_PTR(ret);
1054 }
1055
Rob Clark7f8036b2016-12-07 11:13:53 -05001056 if (gpu->aspace)
1057 msm_mmu_set_fault_handler(gpu->aspace->mmu, gpu, a5xx_fault_handler);
1058
Jordan Crouseb5f103a2016-11-28 12:28:33 -07001059 return gpu;
1060}