blob: c1f8c20414f131b5067a158fdb03f0db0c673b03 [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>
18#include <linux/of_reserved_mem.h>
19#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
29#if IS_ENABLED(CONFIG_QCOM_MDT_LOADER)
30
31static int zap_shader_load_mdt(struct device *dev, const char *fwname)
32{
33 const struct firmware *fw;
34 phys_addr_t mem_phys;
35 ssize_t mem_size;
36 void *mem_region = NULL;
37 int ret;
38
39 /* Request the MDT file for the firmware */
40 ret = request_firmware(&fw, fwname, dev);
41 if (ret) {
42 DRM_DEV_ERROR(dev, "Unable to load %s\n", fwname);
43 return ret;
44 }
45
46 /* Figure out how much memory we need */
47 mem_size = qcom_mdt_get_size(fw);
48 if (mem_size < 0) {
49 ret = mem_size;
50 goto out;
51 }
52
53 /* Allocate memory for the firmware image */
54 mem_region = dmam_alloc_coherent(dev, mem_size, &mem_phys, GFP_KERNEL);
55 if (!mem_region) {
56 ret = -ENOMEM;
57 goto out;
58 }
59
60 /* Load the rest of the MDT */
61 ret = qcom_mdt_load(dev, fw, fwname, GPU_PAS_ID, mem_region, mem_phys,
62 mem_size);
63 if (ret)
64 goto out;
65
66 /* Send the image to the secure world */
67 ret = qcom_scm_pas_auth_and_reset(GPU_PAS_ID);
68 if (ret)
69 DRM_DEV_ERROR(dev, "Unable to authorize the image\n");
70
71out:
72 release_firmware(fw);
73
74 return ret;
75}
76#else
77static int zap_shader_load_mdt(struct device *dev, const char *fwname)
78{
79 return -ENODEV;
80}
81#endif
82
Jordan Crouseb5f103a2016-11-28 12:28:33 -070083static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
84 struct msm_file_private *ctx)
85{
86 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
87 struct msm_drm_private *priv = gpu->dev->dev_private;
88 struct msm_ringbuffer *ring = gpu->rb;
89 unsigned int i, ibs = 0;
90
91 for (i = 0; i < submit->nr_cmds; i++) {
92 switch (submit->cmd[i].type) {
93 case MSM_SUBMIT_CMD_IB_TARGET_BUF:
94 break;
95 case MSM_SUBMIT_CMD_CTX_RESTORE_BUF:
96 if (priv->lastctx == ctx)
97 break;
98 case MSM_SUBMIT_CMD_BUF:
99 OUT_PKT7(ring, CP_INDIRECT_BUFFER_PFE, 3);
100 OUT_RING(ring, lower_32_bits(submit->cmd[i].iova));
101 OUT_RING(ring, upper_32_bits(submit->cmd[i].iova));
102 OUT_RING(ring, submit->cmd[i].size);
103 ibs++;
104 break;
105 }
106 }
107
108 OUT_PKT4(ring, REG_A5XX_CP_SCRATCH_REG(2), 1);
109 OUT_RING(ring, submit->fence->seqno);
110
111 OUT_PKT7(ring, CP_EVENT_WRITE, 4);
112 OUT_RING(ring, CACHE_FLUSH_TS | (1 << 31));
113 OUT_RING(ring, lower_32_bits(rbmemptr(adreno_gpu, fence)));
114 OUT_RING(ring, upper_32_bits(rbmemptr(adreno_gpu, fence)));
115 OUT_RING(ring, submit->fence->seqno);
116
117 gpu->funcs->flush(gpu);
118}
119
Jordan Crouse6e749e52017-07-27 10:42:31 -0600120static const struct {
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700121 u32 offset;
122 u32 value;
Jordan Crouse6e749e52017-07-27 10:42:31 -0600123} a5xx_hwcg[] = {
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700124 {REG_A5XX_RBBM_CLOCK_CNTL_SP0, 0x02222222},
125 {REG_A5XX_RBBM_CLOCK_CNTL_SP1, 0x02222222},
126 {REG_A5XX_RBBM_CLOCK_CNTL_SP2, 0x02222222},
127 {REG_A5XX_RBBM_CLOCK_CNTL_SP3, 0x02222222},
128 {REG_A5XX_RBBM_CLOCK_CNTL2_SP0, 0x02222220},
129 {REG_A5XX_RBBM_CLOCK_CNTL2_SP1, 0x02222220},
130 {REG_A5XX_RBBM_CLOCK_CNTL2_SP2, 0x02222220},
131 {REG_A5XX_RBBM_CLOCK_CNTL2_SP3, 0x02222220},
132 {REG_A5XX_RBBM_CLOCK_HYST_SP0, 0x0000F3CF},
133 {REG_A5XX_RBBM_CLOCK_HYST_SP1, 0x0000F3CF},
134 {REG_A5XX_RBBM_CLOCK_HYST_SP2, 0x0000F3CF},
135 {REG_A5XX_RBBM_CLOCK_HYST_SP3, 0x0000F3CF},
136 {REG_A5XX_RBBM_CLOCK_DELAY_SP0, 0x00000080},
137 {REG_A5XX_RBBM_CLOCK_DELAY_SP1, 0x00000080},
138 {REG_A5XX_RBBM_CLOCK_DELAY_SP2, 0x00000080},
139 {REG_A5XX_RBBM_CLOCK_DELAY_SP3, 0x00000080},
140 {REG_A5XX_RBBM_CLOCK_CNTL_TP0, 0x22222222},
141 {REG_A5XX_RBBM_CLOCK_CNTL_TP1, 0x22222222},
142 {REG_A5XX_RBBM_CLOCK_CNTL_TP2, 0x22222222},
143 {REG_A5XX_RBBM_CLOCK_CNTL_TP3, 0x22222222},
144 {REG_A5XX_RBBM_CLOCK_CNTL2_TP0, 0x22222222},
145 {REG_A5XX_RBBM_CLOCK_CNTL2_TP1, 0x22222222},
146 {REG_A5XX_RBBM_CLOCK_CNTL2_TP2, 0x22222222},
147 {REG_A5XX_RBBM_CLOCK_CNTL2_TP3, 0x22222222},
148 {REG_A5XX_RBBM_CLOCK_CNTL3_TP0, 0x00002222},
149 {REG_A5XX_RBBM_CLOCK_CNTL3_TP1, 0x00002222},
150 {REG_A5XX_RBBM_CLOCK_CNTL3_TP2, 0x00002222},
151 {REG_A5XX_RBBM_CLOCK_CNTL3_TP3, 0x00002222},
152 {REG_A5XX_RBBM_CLOCK_HYST_TP0, 0x77777777},
153 {REG_A5XX_RBBM_CLOCK_HYST_TP1, 0x77777777},
154 {REG_A5XX_RBBM_CLOCK_HYST_TP2, 0x77777777},
155 {REG_A5XX_RBBM_CLOCK_HYST_TP3, 0x77777777},
156 {REG_A5XX_RBBM_CLOCK_HYST2_TP0, 0x77777777},
157 {REG_A5XX_RBBM_CLOCK_HYST2_TP1, 0x77777777},
158 {REG_A5XX_RBBM_CLOCK_HYST2_TP2, 0x77777777},
159 {REG_A5XX_RBBM_CLOCK_HYST2_TP3, 0x77777777},
160 {REG_A5XX_RBBM_CLOCK_HYST3_TP0, 0x00007777},
161 {REG_A5XX_RBBM_CLOCK_HYST3_TP1, 0x00007777},
162 {REG_A5XX_RBBM_CLOCK_HYST3_TP2, 0x00007777},
163 {REG_A5XX_RBBM_CLOCK_HYST3_TP3, 0x00007777},
164 {REG_A5XX_RBBM_CLOCK_DELAY_TP0, 0x11111111},
165 {REG_A5XX_RBBM_CLOCK_DELAY_TP1, 0x11111111},
166 {REG_A5XX_RBBM_CLOCK_DELAY_TP2, 0x11111111},
167 {REG_A5XX_RBBM_CLOCK_DELAY_TP3, 0x11111111},
168 {REG_A5XX_RBBM_CLOCK_DELAY2_TP0, 0x11111111},
169 {REG_A5XX_RBBM_CLOCK_DELAY2_TP1, 0x11111111},
170 {REG_A5XX_RBBM_CLOCK_DELAY2_TP2, 0x11111111},
171 {REG_A5XX_RBBM_CLOCK_DELAY2_TP3, 0x11111111},
172 {REG_A5XX_RBBM_CLOCK_DELAY3_TP0, 0x00001111},
173 {REG_A5XX_RBBM_CLOCK_DELAY3_TP1, 0x00001111},
174 {REG_A5XX_RBBM_CLOCK_DELAY3_TP2, 0x00001111},
175 {REG_A5XX_RBBM_CLOCK_DELAY3_TP3, 0x00001111},
176 {REG_A5XX_RBBM_CLOCK_CNTL_UCHE, 0x22222222},
177 {REG_A5XX_RBBM_CLOCK_CNTL2_UCHE, 0x22222222},
178 {REG_A5XX_RBBM_CLOCK_CNTL3_UCHE, 0x22222222},
179 {REG_A5XX_RBBM_CLOCK_CNTL4_UCHE, 0x00222222},
180 {REG_A5XX_RBBM_CLOCK_HYST_UCHE, 0x00444444},
181 {REG_A5XX_RBBM_CLOCK_DELAY_UCHE, 0x00000002},
182 {REG_A5XX_RBBM_CLOCK_CNTL_RB0, 0x22222222},
183 {REG_A5XX_RBBM_CLOCK_CNTL_RB1, 0x22222222},
184 {REG_A5XX_RBBM_CLOCK_CNTL_RB2, 0x22222222},
185 {REG_A5XX_RBBM_CLOCK_CNTL_RB3, 0x22222222},
186 {REG_A5XX_RBBM_CLOCK_CNTL2_RB0, 0x00222222},
187 {REG_A5XX_RBBM_CLOCK_CNTL2_RB1, 0x00222222},
188 {REG_A5XX_RBBM_CLOCK_CNTL2_RB2, 0x00222222},
189 {REG_A5XX_RBBM_CLOCK_CNTL2_RB3, 0x00222222},
190 {REG_A5XX_RBBM_CLOCK_CNTL_CCU0, 0x00022220},
191 {REG_A5XX_RBBM_CLOCK_CNTL_CCU1, 0x00022220},
192 {REG_A5XX_RBBM_CLOCK_CNTL_CCU2, 0x00022220},
193 {REG_A5XX_RBBM_CLOCK_CNTL_CCU3, 0x00022220},
194 {REG_A5XX_RBBM_CLOCK_CNTL_RAC, 0x05522222},
195 {REG_A5XX_RBBM_CLOCK_CNTL2_RAC, 0x00505555},
196 {REG_A5XX_RBBM_CLOCK_HYST_RB_CCU0, 0x04040404},
197 {REG_A5XX_RBBM_CLOCK_HYST_RB_CCU1, 0x04040404},
198 {REG_A5XX_RBBM_CLOCK_HYST_RB_CCU2, 0x04040404},
199 {REG_A5XX_RBBM_CLOCK_HYST_RB_CCU3, 0x04040404},
200 {REG_A5XX_RBBM_CLOCK_HYST_RAC, 0x07444044},
201 {REG_A5XX_RBBM_CLOCK_DELAY_RB_CCU_L1_0, 0x00000002},
202 {REG_A5XX_RBBM_CLOCK_DELAY_RB_CCU_L1_1, 0x00000002},
203 {REG_A5XX_RBBM_CLOCK_DELAY_RB_CCU_L1_2, 0x00000002},
204 {REG_A5XX_RBBM_CLOCK_DELAY_RB_CCU_L1_3, 0x00000002},
205 {REG_A5XX_RBBM_CLOCK_DELAY_RAC, 0x00010011},
206 {REG_A5XX_RBBM_CLOCK_CNTL_TSE_RAS_RBBM, 0x04222222},
207 {REG_A5XX_RBBM_CLOCK_MODE_GPC, 0x02222222},
208 {REG_A5XX_RBBM_CLOCK_MODE_VFD, 0x00002222},
209 {REG_A5XX_RBBM_CLOCK_HYST_TSE_RAS_RBBM, 0x00000000},
210 {REG_A5XX_RBBM_CLOCK_HYST_GPC, 0x04104004},
211 {REG_A5XX_RBBM_CLOCK_HYST_VFD, 0x00000000},
212 {REG_A5XX_RBBM_CLOCK_DELAY_HLSQ, 0x00000000},
213 {REG_A5XX_RBBM_CLOCK_DELAY_TSE_RAS_RBBM, 0x00004000},
214 {REG_A5XX_RBBM_CLOCK_DELAY_GPC, 0x00000200},
215 {REG_A5XX_RBBM_CLOCK_DELAY_VFD, 0x00002222}
216};
217
Jordan Crouse6e749e52017-07-27 10:42:31 -0600218void a5xx_set_hwcg(struct msm_gpu *gpu, bool state)
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700219{
220 unsigned int i;
221
Jordan Crouse6e749e52017-07-27 10:42:31 -0600222 for (i = 0; i < ARRAY_SIZE(a5xx_hwcg); i++)
223 gpu_write(gpu, a5xx_hwcg[i].offset,
224 state ? a5xx_hwcg[i].value : 0);
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700225
Jordan Crouse6e749e52017-07-27 10:42:31 -0600226 gpu_write(gpu, REG_A5XX_RBBM_CLOCK_CNTL, state ? 0xAAA8AA00 : 0);
227 gpu_write(gpu, REG_A5XX_RBBM_ISDB_CNT, state ? 0x182 : 0x180);
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700228}
229
230static int a5xx_me_init(struct msm_gpu *gpu)
231{
232 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
233 struct msm_ringbuffer *ring = gpu->rb;
234
235 OUT_PKT7(ring, CP_ME_INIT, 8);
236
237 OUT_RING(ring, 0x0000002F);
238
239 /* Enable multiple hardware contexts */
240 OUT_RING(ring, 0x00000003);
241
242 /* Enable error detection */
243 OUT_RING(ring, 0x20000000);
244
245 /* Don't enable header dump */
246 OUT_RING(ring, 0x00000000);
247 OUT_RING(ring, 0x00000000);
248
249 /* Specify workarounds for various microcode issues */
250 if (adreno_is_a530(adreno_gpu)) {
251 /* Workaround for token end syncs
252 * Force a WFI after every direct-render 3D mode draw and every
253 * 2D mode 3 draw
254 */
255 OUT_RING(ring, 0x0000000B);
256 } else {
257 /* No workarounds enabled */
258 OUT_RING(ring, 0x00000000);
259 }
260
261 OUT_RING(ring, 0x00000000);
262 OUT_RING(ring, 0x00000000);
263
264 gpu->funcs->flush(gpu);
265
Jordan Crousee895c7b2017-05-08 14:35:00 -0600266 return a5xx_idle(gpu) ? 0 : -EINVAL;
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700267}
268
269static struct drm_gem_object *a5xx_ucode_load_bo(struct msm_gpu *gpu,
270 const struct firmware *fw, u64 *iova)
271{
272 struct drm_device *drm = gpu->dev;
273 struct drm_gem_object *bo;
274 void *ptr;
275
Sushmita Susheelendra0e082702017-06-13 16:52:54 -0600276 bo = msm_gem_new_locked(drm, fw->size - 4, MSM_BO_UNCACHED);
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700277 if (IS_ERR(bo))
278 return bo;
279
Sushmita Susheelendra0e082702017-06-13 16:52:54 -0600280 ptr = msm_gem_get_vaddr(bo);
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700281 if (!ptr) {
Rob Clarkcb1e3812017-06-13 09:15:36 -0400282 drm_gem_object_unreference(bo);
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700283 return ERR_PTR(-ENOMEM);
284 }
285
286 if (iova) {
Sushmita Susheelendra0e082702017-06-13 16:52:54 -0600287 int ret = msm_gem_get_iova(bo, gpu->aspace, iova);
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700288
289 if (ret) {
Rob Clarkcb1e3812017-06-13 09:15:36 -0400290 drm_gem_object_unreference(bo);
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700291 return ERR_PTR(ret);
292 }
293 }
294
295 memcpy(ptr, &fw->data[4], fw->size - 4);
296
Sushmita Susheelendra0e082702017-06-13 16:52:54 -0600297 msm_gem_put_vaddr(bo);
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700298 return bo;
299}
300
301static int a5xx_ucode_init(struct msm_gpu *gpu)
302{
303 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
304 struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu);
305 int ret;
306
307 if (!a5xx_gpu->pm4_bo) {
308 a5xx_gpu->pm4_bo = a5xx_ucode_load_bo(gpu, adreno_gpu->pm4,
309 &a5xx_gpu->pm4_iova);
310
311 if (IS_ERR(a5xx_gpu->pm4_bo)) {
312 ret = PTR_ERR(a5xx_gpu->pm4_bo);
313 a5xx_gpu->pm4_bo = NULL;
314 dev_err(gpu->dev->dev, "could not allocate PM4: %d\n",
315 ret);
316 return ret;
317 }
318 }
319
320 if (!a5xx_gpu->pfp_bo) {
321 a5xx_gpu->pfp_bo = a5xx_ucode_load_bo(gpu, adreno_gpu->pfp,
322 &a5xx_gpu->pfp_iova);
323
324 if (IS_ERR(a5xx_gpu->pfp_bo)) {
325 ret = PTR_ERR(a5xx_gpu->pfp_bo);
326 a5xx_gpu->pfp_bo = NULL;
327 dev_err(gpu->dev->dev, "could not allocate PFP: %d\n",
328 ret);
329 return ret;
330 }
331 }
332
333 gpu_write64(gpu, REG_A5XX_CP_ME_INSTR_BASE_LO,
334 REG_A5XX_CP_ME_INSTR_BASE_HI, a5xx_gpu->pm4_iova);
335
336 gpu_write64(gpu, REG_A5XX_CP_PFP_INSTR_BASE_LO,
337 REG_A5XX_CP_PFP_INSTR_BASE_HI, a5xx_gpu->pfp_iova);
338
339 return 0;
340}
341
Jordan Crouse7c658172017-05-17 08:45:29 -0600342#define SCM_GPU_ZAP_SHADER_RESUME 0
343
344static int a5xx_zap_shader_resume(struct msm_gpu *gpu)
345{
346 int ret;
347
348 ret = qcom_scm_set_remote_state(SCM_GPU_ZAP_SHADER_RESUME, GPU_PAS_ID);
349 if (ret)
350 DRM_ERROR("%s: zap-shader resume failed: %d\n",
351 gpu->name, ret);
352
353 return ret;
354}
355
356/* Set up a child device to "own" the zap shader */
357static int a5xx_zap_shader_dev_init(struct device *parent, struct device *dev)
358{
359 struct device_node *node;
360 int ret;
361
362 if (dev->parent)
363 return 0;
364
365 /* Find the sub-node for the zap shader */
366 node = of_get_child_by_name(parent->of_node, "zap-shader");
367 if (!node) {
368 DRM_DEV_ERROR(parent, "zap-shader not found in device tree\n");
369 return -ENODEV;
370 }
371
372 dev->parent = parent;
373 dev->of_node = node;
374 dev_set_name(dev, "adreno_zap_shader");
375
376 ret = device_register(dev);
377 if (ret) {
378 DRM_DEV_ERROR(parent, "Couldn't register zap shader device\n");
379 goto out;
380 }
381
382 ret = of_reserved_mem_device_init(dev);
383 if (ret) {
384 DRM_DEV_ERROR(parent, "Unable to set up the reserved memory\n");
385 device_unregister(dev);
386 }
387
388out:
389 if (ret)
390 dev->parent = NULL;
391
392 return ret;
393}
394
395static int a5xx_zap_shader_init(struct msm_gpu *gpu)
396{
397 static bool loaded;
398 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
399 struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu);
400 struct platform_device *pdev = a5xx_gpu->pdev;
401 int ret;
402
403 /*
404 * If the zap shader is already loaded into memory we just need to kick
405 * the remote processor to reinitialize it
406 */
407 if (loaded)
408 return a5xx_zap_shader_resume(gpu);
409
410 /* We need SCM to be able to load the firmware */
411 if (!qcom_scm_is_available()) {
412 DRM_DEV_ERROR(&pdev->dev, "SCM is not available\n");
413 return -EPROBE_DEFER;
414 }
415
416 /* Each GPU has a target specific zap shader firmware name to use */
417 if (!adreno_gpu->info->zapfw) {
418 DRM_DEV_ERROR(&pdev->dev,
419 "Zap shader firmware file not specified for this target\n");
420 return -ENODEV;
421 }
422
423 ret = a5xx_zap_shader_dev_init(&pdev->dev, &a5xx_gpu->zap_dev);
424
425 if (!ret)
426 ret = zap_shader_load_mdt(&a5xx_gpu->zap_dev,
427 adreno_gpu->info->zapfw);
428
429 loaded = !ret;
430
431 return ret;
432}
433
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700434#define A5XX_INT_MASK (A5XX_RBBM_INT_0_MASK_RBBM_AHB_ERROR | \
435 A5XX_RBBM_INT_0_MASK_RBBM_TRANSFER_TIMEOUT | \
436 A5XX_RBBM_INT_0_MASK_RBBM_ME_MS_TIMEOUT | \
437 A5XX_RBBM_INT_0_MASK_RBBM_PFP_MS_TIMEOUT | \
438 A5XX_RBBM_INT_0_MASK_RBBM_ETS_MS_TIMEOUT | \
439 A5XX_RBBM_INT_0_MASK_RBBM_ATB_ASYNC_OVERFLOW | \
440 A5XX_RBBM_INT_0_MASK_CP_HW_ERROR | \
441 A5XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS | \
442 A5XX_RBBM_INT_0_MASK_UCHE_OOB_ACCESS | \
443 A5XX_RBBM_INT_0_MASK_GPMU_VOLTAGE_DROOP)
444
445static int a5xx_hw_init(struct msm_gpu *gpu)
446{
447 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
448 int ret;
449
450 gpu_write(gpu, REG_A5XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x00000003);
451
452 /* Make all blocks contribute to the GPU BUSY perf counter */
453 gpu_write(gpu, REG_A5XX_RBBM_PERFCTR_GPU_BUSY_MASKED, 0xFFFFFFFF);
454
455 /* Enable RBBM error reporting bits */
456 gpu_write(gpu, REG_A5XX_RBBM_AHB_CNTL0, 0x00000001);
457
Rob Clark4e09b952017-01-30 11:15:14 -0500458 if (adreno_gpu->info->quirks & ADRENO_QUIRK_FAULT_DETECT_MASK) {
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700459 /*
460 * Mask out the activity signals from RB1-3 to avoid false
461 * positives
462 */
463
464 gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL11,
465 0xF0000000);
466 gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL12,
467 0xFFFFFFFF);
468 gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL13,
469 0xFFFFFFFF);
470 gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL14,
471 0xFFFFFFFF);
472 gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL15,
473 0xFFFFFFFF);
474 gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL16,
475 0xFFFFFFFF);
476 gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL17,
477 0xFFFFFFFF);
478 gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL18,
479 0xFFFFFFFF);
480 }
481
482 /* Enable fault detection */
483 gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_INT_CNTL,
484 (1 << 30) | 0xFFFF);
485
486 /* Turn on performance counters */
487 gpu_write(gpu, REG_A5XX_RBBM_PERFCTR_CNTL, 0x01);
488
489 /* Increase VFD cache access so LRZ and other data gets evicted less */
490 gpu_write(gpu, REG_A5XX_UCHE_CACHE_WAYS, 0x02);
491
492 /* Disable L2 bypass in the UCHE */
493 gpu_write(gpu, REG_A5XX_UCHE_TRAP_BASE_LO, 0xFFFF0000);
494 gpu_write(gpu, REG_A5XX_UCHE_TRAP_BASE_HI, 0x0001FFFF);
495 gpu_write(gpu, REG_A5XX_UCHE_WRITE_THRU_BASE_LO, 0xFFFF0000);
496 gpu_write(gpu, REG_A5XX_UCHE_WRITE_THRU_BASE_HI, 0x0001FFFF);
497
498 /* Set the GMEM VA range (0 to gpu->gmem) */
499 gpu_write(gpu, REG_A5XX_UCHE_GMEM_RANGE_MIN_LO, 0x00100000);
500 gpu_write(gpu, REG_A5XX_UCHE_GMEM_RANGE_MIN_HI, 0x00000000);
501 gpu_write(gpu, REG_A5XX_UCHE_GMEM_RANGE_MAX_LO,
502 0x00100000 + adreno_gpu->gmem - 1);
503 gpu_write(gpu, REG_A5XX_UCHE_GMEM_RANGE_MAX_HI, 0x00000000);
504
505 gpu_write(gpu, REG_A5XX_CP_MEQ_THRESHOLDS, 0x40);
506 gpu_write(gpu, REG_A5XX_CP_MERCIU_SIZE, 0x40);
507 gpu_write(gpu, REG_A5XX_CP_ROQ_THRESHOLDS_2, 0x80000060);
508 gpu_write(gpu, REG_A5XX_CP_ROQ_THRESHOLDS_1, 0x40201B16);
509
510 gpu_write(gpu, REG_A5XX_PC_DBG_ECO_CNTL, (0x400 << 11 | 0x300 << 22));
511
Rob Clark4e09b952017-01-30 11:15:14 -0500512 if (adreno_gpu->info->quirks & ADRENO_QUIRK_TWO_PASS_USE_WFI)
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700513 gpu_rmw(gpu, REG_A5XX_PC_DBG_ECO_CNTL, 0, (1 << 8));
514
515 gpu_write(gpu, REG_A5XX_PC_DBG_ECO_CNTL, 0xc0200100);
516
517 /* Enable USE_RETENTION_FLOPS */
518 gpu_write(gpu, REG_A5XX_CP_CHICKEN_DBG, 0x02000000);
519
520 /* Enable ME/PFP split notification */
521 gpu_write(gpu, REG_A5XX_RBBM_AHB_CNTL1, 0xA6FFFFFF);
522
523 /* Enable HWCG */
Jordan Crouse6e749e52017-07-27 10:42:31 -0600524 a5xx_set_hwcg(gpu, true);
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700525
526 gpu_write(gpu, REG_A5XX_RBBM_AHB_CNTL2, 0x0000003F);
527
528 /* Set the highest bank bit */
529 gpu_write(gpu, REG_A5XX_TPL1_MODE_CNTL, 2 << 7);
530 gpu_write(gpu, REG_A5XX_RB_MODE_CNTL, 2 << 1);
531
532 /* Protect registers from the CP */
533 gpu_write(gpu, REG_A5XX_CP_PROTECT_CNTL, 0x00000007);
534
535 /* RBBM */
536 gpu_write(gpu, REG_A5XX_CP_PROTECT(0), ADRENO_PROTECT_RW(0x04, 4));
537 gpu_write(gpu, REG_A5XX_CP_PROTECT(1), ADRENO_PROTECT_RW(0x08, 8));
538 gpu_write(gpu, REG_A5XX_CP_PROTECT(2), ADRENO_PROTECT_RW(0x10, 16));
539 gpu_write(gpu, REG_A5XX_CP_PROTECT(3), ADRENO_PROTECT_RW(0x20, 32));
540 gpu_write(gpu, REG_A5XX_CP_PROTECT(4), ADRENO_PROTECT_RW(0x40, 64));
541 gpu_write(gpu, REG_A5XX_CP_PROTECT(5), ADRENO_PROTECT_RW(0x80, 64));
542
543 /* Content protect */
544 gpu_write(gpu, REG_A5XX_CP_PROTECT(6),
545 ADRENO_PROTECT_RW(REG_A5XX_RBBM_SECVID_TSB_TRUSTED_BASE_LO,
546 16));
547 gpu_write(gpu, REG_A5XX_CP_PROTECT(7),
548 ADRENO_PROTECT_RW(REG_A5XX_RBBM_SECVID_TRUST_CNTL, 2));
549
550 /* CP */
551 gpu_write(gpu, REG_A5XX_CP_PROTECT(8), ADRENO_PROTECT_RW(0x800, 64));
552 gpu_write(gpu, REG_A5XX_CP_PROTECT(9), ADRENO_PROTECT_RW(0x840, 8));
553 gpu_write(gpu, REG_A5XX_CP_PROTECT(10), ADRENO_PROTECT_RW(0x880, 32));
554 gpu_write(gpu, REG_A5XX_CP_PROTECT(11), ADRENO_PROTECT_RW(0xAA0, 1));
555
556 /* RB */
557 gpu_write(gpu, REG_A5XX_CP_PROTECT(12), ADRENO_PROTECT_RW(0xCC0, 1));
558 gpu_write(gpu, REG_A5XX_CP_PROTECT(13), ADRENO_PROTECT_RW(0xCF0, 2));
559
560 /* VPC */
561 gpu_write(gpu, REG_A5XX_CP_PROTECT(14), ADRENO_PROTECT_RW(0xE68, 8));
562 gpu_write(gpu, REG_A5XX_CP_PROTECT(15), ADRENO_PROTECT_RW(0xE70, 4));
563
564 /* UCHE */
565 gpu_write(gpu, REG_A5XX_CP_PROTECT(16), ADRENO_PROTECT_RW(0xE80, 16));
566
567 if (adreno_is_a530(adreno_gpu))
568 gpu_write(gpu, REG_A5XX_CP_PROTECT(17),
569 ADRENO_PROTECT_RW(0x10000, 0x8000));
570
571 gpu_write(gpu, REG_A5XX_RBBM_SECVID_TSB_CNTL, 0);
572 /*
573 * Disable the trusted memory range - we don't actually supported secure
574 * memory rendering at this point in time and we don't want to block off
575 * part of the virtual memory space.
576 */
577 gpu_write64(gpu, REG_A5XX_RBBM_SECVID_TSB_TRUSTED_BASE_LO,
578 REG_A5XX_RBBM_SECVID_TSB_TRUSTED_BASE_HI, 0x00000000);
579 gpu_write(gpu, REG_A5XX_RBBM_SECVID_TSB_TRUSTED_SIZE, 0x00000000);
580
Jordan Crouse2401a002016-11-28 12:28:34 -0700581 /* Load the GPMU firmware before starting the HW init */
582 a5xx_gpmu_ucode_init(gpu);
583
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700584 ret = adreno_hw_init(gpu);
585 if (ret)
586 return ret;
587
588 ret = a5xx_ucode_init(gpu);
589 if (ret)
590 return ret;
591
592 /* Disable the interrupts through the initial bringup stage */
593 gpu_write(gpu, REG_A5XX_RBBM_INT_0_MASK, A5XX_INT_MASK);
594
595 /* Clear ME_HALT to start the micro engine */
596 gpu_write(gpu, REG_A5XX_CP_PFP_ME_CNTL, 0);
597 ret = a5xx_me_init(gpu);
598 if (ret)
599 return ret;
600
Jordan Crouse2401a002016-11-28 12:28:34 -0700601 ret = a5xx_power_init(gpu);
602 if (ret)
603 return ret;
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700604
605 /*
606 * Send a pipeline event stat to get misbehaving counters to start
607 * ticking correctly
608 */
609 if (adreno_is_a530(adreno_gpu)) {
610 OUT_PKT7(gpu->rb, CP_EVENT_WRITE, 1);
611 OUT_RING(gpu->rb, 0x0F);
612
613 gpu->funcs->flush(gpu);
Jordan Crousee895c7b2017-05-08 14:35:00 -0600614 if (!a5xx_idle(gpu))
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700615 return -EINVAL;
616 }
617
Jordan Crouse7c658172017-05-17 08:45:29 -0600618 /*
619 * Try to load a zap shader into the secure world. If successful
620 * we can use the CP to switch out of secure mode. If not then we
621 * have no resource but to try to switch ourselves out manually. If we
622 * guessed wrong then access to the RBBM_SECVID_TRUST_CNTL register will
623 * be blocked and a permissions violation will soon follow.
624 */
625 ret = a5xx_zap_shader_init(gpu);
626 if (!ret) {
627 OUT_PKT7(gpu->rb, CP_SET_SECURE_MODE, 1);
628 OUT_RING(gpu->rb, 0x00000000);
629
630 gpu->funcs->flush(gpu);
Jordan Crousee895c7b2017-05-08 14:35:00 -0600631 if (!a5xx_idle(gpu))
Jordan Crouse7c658172017-05-17 08:45:29 -0600632 return -EINVAL;
633 } else {
634 /* Print a warning so if we die, we know why */
635 dev_warn_once(gpu->dev->dev,
636 "Zap shader not enabled - using SECVID_TRUST_CNTL instead\n");
637 gpu_write(gpu, REG_A5XX_RBBM_SECVID_TRUST_CNTL, 0x0);
638 }
Jordan Crouse2401a002016-11-28 12:28:34 -0700639
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700640 return 0;
641}
642
643static void a5xx_recover(struct msm_gpu *gpu)
644{
645 int i;
646
647 adreno_dump_info(gpu);
648
649 for (i = 0; i < 8; i++) {
650 printk("CP_SCRATCH_REG%d: %u\n", i,
651 gpu_read(gpu, REG_A5XX_CP_SCRATCH_REG(i)));
652 }
653
654 if (hang_debug)
655 a5xx_dump(gpu);
656
657 gpu_write(gpu, REG_A5XX_RBBM_SW_RESET_CMD, 1);
658 gpu_read(gpu, REG_A5XX_RBBM_SW_RESET_CMD);
659 gpu_write(gpu, REG_A5XX_RBBM_SW_RESET_CMD, 0);
660 adreno_recover(gpu);
661}
662
663static void a5xx_destroy(struct msm_gpu *gpu)
664{
665 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
666 struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu);
667
668 DBG("%s", gpu->name);
669
Jordan Crouse7c658172017-05-17 08:45:29 -0600670 if (a5xx_gpu->zap_dev.parent)
671 device_unregister(&a5xx_gpu->zap_dev);
672
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700673 if (a5xx_gpu->pm4_bo) {
674 if (a5xx_gpu->pm4_iova)
Rob Clark8bdcd942017-06-13 11:07:08 -0400675 msm_gem_put_iova(a5xx_gpu->pm4_bo, gpu->aspace);
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700676 drm_gem_object_unreference_unlocked(a5xx_gpu->pm4_bo);
677 }
678
679 if (a5xx_gpu->pfp_bo) {
680 if (a5xx_gpu->pfp_iova)
Rob Clark8bdcd942017-06-13 11:07:08 -0400681 msm_gem_put_iova(a5xx_gpu->pfp_bo, gpu->aspace);
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700682 drm_gem_object_unreference_unlocked(a5xx_gpu->pfp_bo);
683 }
684
Jordan Crouse2401a002016-11-28 12:28:34 -0700685 if (a5xx_gpu->gpmu_bo) {
Jordan Crouse2002c9c2017-03-07 09:50:27 -0700686 if (a5xx_gpu->gpmu_iova)
Rob Clark8bdcd942017-06-13 11:07:08 -0400687 msm_gem_put_iova(a5xx_gpu->gpmu_bo, gpu->aspace);
Jordan Crouse2401a002016-11-28 12:28:34 -0700688 drm_gem_object_unreference_unlocked(a5xx_gpu->gpmu_bo);
689 }
690
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700691 adreno_gpu_cleanup(adreno_gpu);
692 kfree(a5xx_gpu);
693}
694
695static inline bool _a5xx_check_idle(struct msm_gpu *gpu)
696{
697 if (gpu_read(gpu, REG_A5XX_RBBM_STATUS) & ~A5XX_RBBM_STATUS_HI_BUSY)
698 return false;
699
700 /*
701 * Nearly every abnormality ends up pausing the GPU and triggering a
702 * fault so we can safely just watch for this one interrupt to fire
703 */
704 return !(gpu_read(gpu, REG_A5XX_RBBM_INT_0_STATUS) &
705 A5XX_RBBM_INT_0_MASK_MISC_HANG_DETECT);
706}
707
Jordan Crousee895c7b2017-05-08 14:35:00 -0600708bool a5xx_idle(struct msm_gpu *gpu)
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700709{
710 /* wait for CP to drain ringbuffer: */
711 if (!adreno_idle(gpu))
712 return false;
713
714 if (spin_until(_a5xx_check_idle(gpu))) {
715 DRM_ERROR("%s: %ps: timeout waiting for GPU to idle: status %8.8X irq %8.8X\n",
716 gpu->name, __builtin_return_address(0),
717 gpu_read(gpu, REG_A5XX_RBBM_STATUS),
718 gpu_read(gpu, REG_A5XX_RBBM_INT_0_STATUS));
719
720 return false;
721 }
722
723 return true;
724}
725
Rob Clark7f8036b2016-12-07 11:13:53 -0500726static int a5xx_fault_handler(void *arg, unsigned long iova, int flags)
727{
728 struct msm_gpu *gpu = arg;
729 pr_warn_ratelimited("*** gpu fault: iova=%08lx, flags=%d (%u,%u,%u,%u)\n",
730 iova, flags,
731 gpu_read(gpu, REG_A5XX_CP_SCRATCH_REG(4)),
732 gpu_read(gpu, REG_A5XX_CP_SCRATCH_REG(5)),
733 gpu_read(gpu, REG_A5XX_CP_SCRATCH_REG(6)),
734 gpu_read(gpu, REG_A5XX_CP_SCRATCH_REG(7)));
735
736 return -EFAULT;
737}
738
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700739static void a5xx_cp_err_irq(struct msm_gpu *gpu)
740{
741 u32 status = gpu_read(gpu, REG_A5XX_CP_INTERRUPT_STATUS);
742
743 if (status & A5XX_CP_INT_CP_OPCODE_ERROR) {
744 u32 val;
745
746 gpu_write(gpu, REG_A5XX_CP_PFP_STAT_ADDR, 0);
747
748 /*
749 * REG_A5XX_CP_PFP_STAT_DATA is indexed, and we want index 1 so
750 * read it twice
751 */
752
753 gpu_read(gpu, REG_A5XX_CP_PFP_STAT_DATA);
754 val = gpu_read(gpu, REG_A5XX_CP_PFP_STAT_DATA);
755
756 dev_err_ratelimited(gpu->dev->dev, "CP | opcode error | possible opcode=0x%8.8X\n",
757 val);
758 }
759
760 if (status & A5XX_CP_INT_CP_HW_FAULT_ERROR)
761 dev_err_ratelimited(gpu->dev->dev, "CP | HW fault | status=0x%8.8X\n",
762 gpu_read(gpu, REG_A5XX_CP_HW_FAULT));
763
764 if (status & A5XX_CP_INT_CP_DMA_ERROR)
765 dev_err_ratelimited(gpu->dev->dev, "CP | DMA error\n");
766
767 if (status & A5XX_CP_INT_CP_REGISTER_PROTECTION_ERROR) {
768 u32 val = gpu_read(gpu, REG_A5XX_CP_PROTECT_STATUS);
769
770 dev_err_ratelimited(gpu->dev->dev,
771 "CP | protected mode error | %s | addr=0x%8.8X | status=0x%8.8X\n",
772 val & (1 << 24) ? "WRITE" : "READ",
773 (val & 0xFFFFF) >> 2, val);
774 }
775
776 if (status & A5XX_CP_INT_CP_AHB_ERROR) {
777 u32 status = gpu_read(gpu, REG_A5XX_CP_AHB_FAULT);
778 const char *access[16] = { "reserved", "reserved",
779 "timestamp lo", "timestamp hi", "pfp read", "pfp write",
780 "", "", "me read", "me write", "", "", "crashdump read",
781 "crashdump write" };
782
783 dev_err_ratelimited(gpu->dev->dev,
784 "CP | AHB error | addr=%X access=%s error=%d | status=0x%8.8X\n",
785 status & 0xFFFFF, access[(status >> 24) & 0xF],
786 (status & (1 << 31)), status);
787 }
788}
789
Jordan Crouse7352fb52017-03-07 09:50:29 -0700790static void a5xx_rbbm_err_irq(struct msm_gpu *gpu, u32 status)
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700791{
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700792 if (status & A5XX_RBBM_INT_0_MASK_RBBM_AHB_ERROR) {
793 u32 val = gpu_read(gpu, REG_A5XX_RBBM_AHB_ERROR_STATUS);
794
795 dev_err_ratelimited(gpu->dev->dev,
796 "RBBM | AHB bus error | %s | addr=0x%X | ports=0x%X:0x%X\n",
797 val & (1 << 28) ? "WRITE" : "READ",
798 (val & 0xFFFFF) >> 2, (val >> 20) & 0x3,
799 (val >> 24) & 0xF);
800
801 /* Clear the error */
802 gpu_write(gpu, REG_A5XX_RBBM_AHB_CMD, (1 << 4));
Jordan Crouse7352fb52017-03-07 09:50:29 -0700803
804 /* Clear the interrupt */
805 gpu_write(gpu, REG_A5XX_RBBM_INT_CLEAR_CMD,
806 A5XX_RBBM_INT_0_MASK_RBBM_AHB_ERROR);
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700807 }
808
809 if (status & A5XX_RBBM_INT_0_MASK_RBBM_TRANSFER_TIMEOUT)
810 dev_err_ratelimited(gpu->dev->dev, "RBBM | AHB transfer timeout\n");
811
812 if (status & A5XX_RBBM_INT_0_MASK_RBBM_ME_MS_TIMEOUT)
813 dev_err_ratelimited(gpu->dev->dev, "RBBM | ME master split | status=0x%X\n",
814 gpu_read(gpu, REG_A5XX_RBBM_AHB_ME_SPLIT_STATUS));
815
816 if (status & A5XX_RBBM_INT_0_MASK_RBBM_PFP_MS_TIMEOUT)
817 dev_err_ratelimited(gpu->dev->dev, "RBBM | PFP master split | status=0x%X\n",
818 gpu_read(gpu, REG_A5XX_RBBM_AHB_PFP_SPLIT_STATUS));
819
820 if (status & A5XX_RBBM_INT_0_MASK_RBBM_ETS_MS_TIMEOUT)
821 dev_err_ratelimited(gpu->dev->dev, "RBBM | ETS master split | status=0x%X\n",
822 gpu_read(gpu, REG_A5XX_RBBM_AHB_ETS_SPLIT_STATUS));
823
824 if (status & A5XX_RBBM_INT_0_MASK_RBBM_ATB_ASYNC_OVERFLOW)
825 dev_err_ratelimited(gpu->dev->dev, "RBBM | ATB ASYNC overflow\n");
826
827 if (status & A5XX_RBBM_INT_0_MASK_RBBM_ATB_BUS_OVERFLOW)
828 dev_err_ratelimited(gpu->dev->dev, "RBBM | ATB bus overflow\n");
829}
830
831static void a5xx_uche_err_irq(struct msm_gpu *gpu)
832{
833 uint64_t addr = (uint64_t) gpu_read(gpu, REG_A5XX_UCHE_TRAP_LOG_HI);
834
835 addr |= gpu_read(gpu, REG_A5XX_UCHE_TRAP_LOG_LO);
836
837 dev_err_ratelimited(gpu->dev->dev, "UCHE | Out of bounds access | addr=0x%llX\n",
838 addr);
839}
840
841static void a5xx_gpmu_err_irq(struct msm_gpu *gpu)
842{
843 dev_err_ratelimited(gpu->dev->dev, "GPMU | voltage droop\n");
844}
845
846#define RBBM_ERROR_MASK \
847 (A5XX_RBBM_INT_0_MASK_RBBM_AHB_ERROR | \
848 A5XX_RBBM_INT_0_MASK_RBBM_TRANSFER_TIMEOUT | \
849 A5XX_RBBM_INT_0_MASK_RBBM_ME_MS_TIMEOUT | \
850 A5XX_RBBM_INT_0_MASK_RBBM_PFP_MS_TIMEOUT | \
851 A5XX_RBBM_INT_0_MASK_RBBM_ETS_MS_TIMEOUT | \
852 A5XX_RBBM_INT_0_MASK_RBBM_ATB_ASYNC_OVERFLOW)
853
854static irqreturn_t a5xx_irq(struct msm_gpu *gpu)
855{
856 u32 status = gpu_read(gpu, REG_A5XX_RBBM_INT_0_STATUS);
857
Jordan Crouse7352fb52017-03-07 09:50:29 -0700858 /*
859 * Clear all the interrupts except RBBM_AHB_ERROR - if we clear it
860 * before the source is cleared the interrupt will storm.
861 */
862 gpu_write(gpu, REG_A5XX_RBBM_INT_CLEAR_CMD,
863 status & ~A5XX_RBBM_INT_0_MASK_RBBM_AHB_ERROR);
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700864
Jordan Crouse7352fb52017-03-07 09:50:29 -0700865 /* Pass status to a5xx_rbbm_err_irq because we've already cleared it */
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700866 if (status & RBBM_ERROR_MASK)
Jordan Crouse7352fb52017-03-07 09:50:29 -0700867 a5xx_rbbm_err_irq(gpu, status);
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700868
869 if (status & A5XX_RBBM_INT_0_MASK_CP_HW_ERROR)
870 a5xx_cp_err_irq(gpu);
871
872 if (status & A5XX_RBBM_INT_0_MASK_UCHE_OOB_ACCESS)
873 a5xx_uche_err_irq(gpu);
874
875 if (status & A5XX_RBBM_INT_0_MASK_GPMU_VOLTAGE_DROOP)
876 a5xx_gpmu_err_irq(gpu);
877
878 if (status & A5XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS)
879 msm_gpu_retire(gpu);
880
881 return IRQ_HANDLED;
882}
883
884static const u32 a5xx_register_offsets[REG_ADRENO_REGISTER_MAX] = {
885 REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_BASE, REG_A5XX_CP_RB_BASE),
886 REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_BASE_HI, REG_A5XX_CP_RB_BASE_HI),
887 REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_RPTR_ADDR, REG_A5XX_CP_RB_RPTR_ADDR),
888 REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_RPTR_ADDR_HI,
889 REG_A5XX_CP_RB_RPTR_ADDR_HI),
890 REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_RPTR, REG_A5XX_CP_RB_RPTR),
891 REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_WPTR, REG_A5XX_CP_RB_WPTR),
892 REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_CNTL, REG_A5XX_CP_RB_CNTL),
893};
894
895static const u32 a5xx_registers[] = {
896 0x0000, 0x0002, 0x0004, 0x0020, 0x0022, 0x0026, 0x0029, 0x002B,
897 0x002E, 0x0035, 0x0038, 0x0042, 0x0044, 0x0044, 0x0047, 0x0095,
898 0x0097, 0x00BB, 0x03A0, 0x0464, 0x0469, 0x046F, 0x04D2, 0x04D3,
Jordan Crouse3394f562017-07-27 10:42:30 -0600899 0x04E0, 0x0533, 0x0540, 0x0555, 0x0800, 0x081A, 0x081F, 0x0841,
900 0x0860, 0x0860, 0x0880, 0x08A0, 0x0B00, 0x0B12, 0x0B15, 0x0B28,
901 0x0B78, 0x0B7F, 0x0BB0, 0x0BBD, 0x0BC0, 0x0BC6, 0x0BD0, 0x0C53,
902 0x0C60, 0x0C61, 0x0C80, 0x0C82, 0x0C84, 0x0C85, 0x0C90, 0x0C98,
903 0x0CA0, 0x0CA0, 0x0CB0, 0x0CB2, 0x2180, 0x2185, 0x2580, 0x2585,
904 0x0CC1, 0x0CC1, 0x0CC4, 0x0CC7, 0x0CCC, 0x0CCC, 0x0CD0, 0x0CD8,
905 0x0CE0, 0x0CE5, 0x0CE8, 0x0CE8, 0x0CEC, 0x0CF1, 0x0CFB, 0x0D0E,
906 0x2100, 0x211E, 0x2140, 0x2145, 0x2500, 0x251E, 0x2540, 0x2545,
907 0x0D10, 0x0D17, 0x0D20, 0x0D23, 0x0D30, 0x0D30, 0x20C0, 0x20C0,
908 0x24C0, 0x24C0, 0x0E40, 0x0E43, 0x0E4A, 0x0E4A, 0x0E50, 0x0E57,
909 0x0E60, 0x0E7C, 0x0E80, 0x0E8E, 0x0E90, 0x0E96, 0x0EA0, 0x0EA8,
910 0x0EB0, 0x0EB2, 0xE140, 0xE147, 0xE150, 0xE187, 0xE1A0, 0xE1A9,
911 0xE1B0, 0xE1B6, 0xE1C0, 0xE1C7, 0xE1D0, 0xE1D1, 0xE200, 0xE201,
912 0xE210, 0xE21C, 0xE240, 0xE268, 0xE000, 0xE006, 0xE010, 0xE09A,
913 0xE0A0, 0xE0A4, 0xE0AA, 0xE0EB, 0xE100, 0xE105, 0xE380, 0xE38F,
914 0xE3B0, 0xE3B0, 0xE400, 0xE405, 0xE408, 0xE4E9, 0xE4F0, 0xE4F0,
915 0xE280, 0xE280, 0xE282, 0xE2A3, 0xE2A5, 0xE2C2, 0xE940, 0xE947,
916 0xE950, 0xE987, 0xE9A0, 0xE9A9, 0xE9B0, 0xE9B6, 0xE9C0, 0xE9C7,
917 0xE9D0, 0xE9D1, 0xEA00, 0xEA01, 0xEA10, 0xEA1C, 0xEA40, 0xEA68,
918 0xE800, 0xE806, 0xE810, 0xE89A, 0xE8A0, 0xE8A4, 0xE8AA, 0xE8EB,
919 0xE900, 0xE905, 0xEB80, 0xEB8F, 0xEBB0, 0xEBB0, 0xEC00, 0xEC05,
920 0xEC08, 0xECE9, 0xECF0, 0xECF0, 0xEA80, 0xEA80, 0xEA82, 0xEAA3,
921 0xEAA5, 0xEAC2, 0xA800, 0xA8FF, 0xAC60, 0xAC60, 0xB000, 0xB97F,
922 0xB9A0, 0xB9BF, ~0
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700923};
924
925static void a5xx_dump(struct msm_gpu *gpu)
926{
927 dev_info(gpu->dev->dev, "status: %08x\n",
928 gpu_read(gpu, REG_A5XX_RBBM_STATUS));
929 adreno_dump(gpu);
930}
931
932static int a5xx_pm_resume(struct msm_gpu *gpu)
933{
Jordan Crouse2401a002016-11-28 12:28:34 -0700934 int ret;
935
936 /* Turn on the core power */
937 ret = msm_gpu_pm_resume(gpu);
938 if (ret)
939 return ret;
940
941 /* Turn the RBCCU domain first to limit the chances of voltage droop */
942 gpu_write(gpu, REG_A5XX_GPMU_RBCCU_POWER_CNTL, 0x778000);
943
944 /* Wait 3 usecs before polling */
945 udelay(3);
946
947 ret = spin_usecs(gpu, 20, REG_A5XX_GPMU_RBCCU_PWR_CLK_STATUS,
948 (1 << 20), (1 << 20));
949 if (ret) {
950 DRM_ERROR("%s: timeout waiting for RBCCU GDSC enable: %X\n",
951 gpu->name,
952 gpu_read(gpu, REG_A5XX_GPMU_RBCCU_PWR_CLK_STATUS));
953 return ret;
954 }
955
956 /* Turn on the SP domain */
957 gpu_write(gpu, REG_A5XX_GPMU_SP_POWER_CNTL, 0x778000);
958 ret = spin_usecs(gpu, 20, REG_A5XX_GPMU_SP_PWR_CLK_STATUS,
959 (1 << 20), (1 << 20));
960 if (ret)
961 DRM_ERROR("%s: timeout waiting for SP GDSC enable\n",
962 gpu->name);
963
964 return ret;
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700965}
966
967static int a5xx_pm_suspend(struct msm_gpu *gpu)
968{
Jordan Crouse2401a002016-11-28 12:28:34 -0700969 /* Clear the VBIF pipe before shutting down */
970 gpu_write(gpu, REG_A5XX_VBIF_XIN_HALT_CTRL0, 0xF);
971 spin_until((gpu_read(gpu, REG_A5XX_VBIF_XIN_HALT_CTRL1) & 0xF) == 0xF);
972
973 gpu_write(gpu, REG_A5XX_VBIF_XIN_HALT_CTRL0, 0);
974
975 /*
976 * Reset the VBIF before power collapse to avoid issue with FIFO
977 * entries
978 */
979 gpu_write(gpu, REG_A5XX_RBBM_BLOCK_SW_RESET_CMD, 0x003C0000);
980 gpu_write(gpu, REG_A5XX_RBBM_BLOCK_SW_RESET_CMD, 0x00000000);
981
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700982 return msm_gpu_pm_suspend(gpu);
983}
984
985static int a5xx_get_timestamp(struct msm_gpu *gpu, uint64_t *value)
986{
987 *value = gpu_read64(gpu, REG_A5XX_RBBM_PERFCTR_CP_0_LO,
988 REG_A5XX_RBBM_PERFCTR_CP_0_HI);
989
990 return 0;
991}
992
993#ifdef CONFIG_DEBUG_FS
994static void a5xx_show(struct msm_gpu *gpu, struct seq_file *m)
995{
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700996 seq_printf(m, "status: %08x\n",
997 gpu_read(gpu, REG_A5XX_RBBM_STATUS));
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700998 adreno_show(gpu, m);
999}
1000#endif
1001
1002static const struct adreno_gpu_funcs funcs = {
1003 .base = {
1004 .get_param = adreno_get_param,
1005 .hw_init = a5xx_hw_init,
1006 .pm_suspend = a5xx_pm_suspend,
1007 .pm_resume = a5xx_pm_resume,
1008 .recover = a5xx_recover,
1009 .last_fence = adreno_last_fence,
1010 .submit = a5xx_submit,
1011 .flush = adreno_flush,
Jordan Crouseb5f103a2016-11-28 12:28:33 -07001012 .irq = a5xx_irq,
1013 .destroy = a5xx_destroy,
Arnd Bergmann0c3eaf12017-03-13 17:43:48 +01001014#ifdef CONFIG_DEBUG_FS
Jordan Crouseb5f103a2016-11-28 12:28:33 -07001015 .show = a5xx_show,
Arnd Bergmann0c3eaf12017-03-13 17:43:48 +01001016#endif
Jordan Crouseb5f103a2016-11-28 12:28:33 -07001017 },
1018 .get_timestamp = a5xx_get_timestamp,
1019};
1020
1021struct msm_gpu *a5xx_gpu_init(struct drm_device *dev)
1022{
1023 struct msm_drm_private *priv = dev->dev_private;
1024 struct platform_device *pdev = priv->gpu_pdev;
1025 struct a5xx_gpu *a5xx_gpu = NULL;
1026 struct adreno_gpu *adreno_gpu;
1027 struct msm_gpu *gpu;
1028 int ret;
1029
1030 if (!pdev) {
1031 dev_err(dev->dev, "No A5XX device is defined\n");
1032 return ERR_PTR(-ENXIO);
1033 }
1034
1035 a5xx_gpu = kzalloc(sizeof(*a5xx_gpu), GFP_KERNEL);
1036 if (!a5xx_gpu)
1037 return ERR_PTR(-ENOMEM);
1038
1039 adreno_gpu = &a5xx_gpu->base;
1040 gpu = &adreno_gpu->base;
1041
1042 a5xx_gpu->pdev = pdev;
1043 adreno_gpu->registers = a5xx_registers;
1044 adreno_gpu->reg_offsets = a5xx_register_offsets;
1045
Jordan Crouse2401a002016-11-28 12:28:34 -07001046 a5xx_gpu->lm_leakage = 0x4E001A;
1047
Jordan Crouseb5f103a2016-11-28 12:28:33 -07001048 ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs);
1049 if (ret) {
1050 a5xx_destroy(&(a5xx_gpu->base.base));
1051 return ERR_PTR(ret);
1052 }
1053
Rob Clark7f8036b2016-12-07 11:13:53 -05001054 if (gpu->aspace)
1055 msm_mmu_set_fault_handler(gpu->aspace->mmu, gpu, a5xx_fault_handler);
1056
Jordan Crouseb5f103a2016-11-28 12:28:33 -07001057 return gpu;
1058}