blob: 1f4a0322b1279f4318588d347ff408ecbfc9a108 [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
Jordan Crouse7c658172017-05-17 08:45:29 -060029static int zap_shader_load_mdt(struct device *dev, const char *fwname)
30{
31 const struct firmware *fw;
Arnd Bergmann8f93e042017-07-26 21:59:21 +020032 struct device_node *np;
33 struct resource r;
Jordan Crouse7c658172017-05-17 08:45:29 -060034 phys_addr_t mem_phys;
35 ssize_t mem_size;
36 void *mem_region = NULL;
37 int ret;
38
Arnd Bergmannbdab8e82017-07-26 17:52:44 +020039 if (!IS_ENABLED(CONFIG_ARCH_QCOM))
40 return -EINVAL;
41
Arnd Bergmann8f93e042017-07-26 21:59:21 +020042 np = of_get_child_by_name(dev->of_node, "zap-shader");
43 if (!np)
44 return -ENODEV;
45
46 np = of_parse_phandle(np, "memory-region", 0);
47 if (!np)
48 return -EINVAL;
49
50 ret = of_address_to_resource(np, 0, &r);
51 if (ret)
52 return ret;
53
54 mem_phys = r.start;
55 mem_size = resource_size(&r);
56
Jordan Crouse7c658172017-05-17 08:45:29 -060057 /* Request the MDT file for the firmware */
58 ret = request_firmware(&fw, fwname, dev);
59 if (ret) {
60 DRM_DEV_ERROR(dev, "Unable to load %s\n", fwname);
61 return ret;
62 }
63
64 /* Figure out how much memory we need */
65 mem_size = qcom_mdt_get_size(fw);
66 if (mem_size < 0) {
67 ret = mem_size;
68 goto out;
69 }
70
71 /* Allocate memory for the firmware image */
Arnd Bergmann8f93e042017-07-26 21:59:21 +020072 mem_region = memremap(mem_phys, mem_size, MEMREMAP_WC);
Jordan Crouse7c658172017-05-17 08:45:29 -060073 if (!mem_region) {
74 ret = -ENOMEM;
75 goto out;
76 }
77
78 /* Load the rest of the MDT */
79 ret = qcom_mdt_load(dev, fw, fwname, GPU_PAS_ID, mem_region, mem_phys,
80 mem_size);
81 if (ret)
82 goto out;
83
84 /* Send the image to the secure world */
85 ret = qcom_scm_pas_auth_and_reset(GPU_PAS_ID);
86 if (ret)
87 DRM_DEV_ERROR(dev, "Unable to authorize the image\n");
88
89out:
Arnd Bergmann8f93e042017-07-26 21:59:21 +020090 if (mem_region)
91 memunmap(mem_region);
92
Jordan Crouse7c658172017-05-17 08:45:29 -060093 release_firmware(fw);
94
95 return ret;
96}
Jordan Crouse7c658172017-05-17 08:45:29 -060097
Jordan Crouseb5f103a2016-11-28 12:28:33 -070098static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
99 struct msm_file_private *ctx)
100{
101 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
102 struct msm_drm_private *priv = gpu->dev->dev_private;
103 struct msm_ringbuffer *ring = gpu->rb;
104 unsigned int i, ibs = 0;
105
106 for (i = 0; i < submit->nr_cmds; i++) {
107 switch (submit->cmd[i].type) {
108 case MSM_SUBMIT_CMD_IB_TARGET_BUF:
109 break;
110 case MSM_SUBMIT_CMD_CTX_RESTORE_BUF:
111 if (priv->lastctx == ctx)
112 break;
113 case MSM_SUBMIT_CMD_BUF:
114 OUT_PKT7(ring, CP_INDIRECT_BUFFER_PFE, 3);
115 OUT_RING(ring, lower_32_bits(submit->cmd[i].iova));
116 OUT_RING(ring, upper_32_bits(submit->cmd[i].iova));
117 OUT_RING(ring, submit->cmd[i].size);
118 ibs++;
119 break;
120 }
121 }
122
123 OUT_PKT4(ring, REG_A5XX_CP_SCRATCH_REG(2), 1);
124 OUT_RING(ring, submit->fence->seqno);
125
126 OUT_PKT7(ring, CP_EVENT_WRITE, 4);
127 OUT_RING(ring, CACHE_FLUSH_TS | (1 << 31));
128 OUT_RING(ring, lower_32_bits(rbmemptr(adreno_gpu, fence)));
129 OUT_RING(ring, upper_32_bits(rbmemptr(adreno_gpu, fence)));
130 OUT_RING(ring, submit->fence->seqno);
131
132 gpu->funcs->flush(gpu);
133}
134
Jordan Crouse6e749e52017-07-27 10:42:31 -0600135static const struct {
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700136 u32 offset;
137 u32 value;
Jordan Crouse6e749e52017-07-27 10:42:31 -0600138} a5xx_hwcg[] = {
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700139 {REG_A5XX_RBBM_CLOCK_CNTL_SP0, 0x02222222},
140 {REG_A5XX_RBBM_CLOCK_CNTL_SP1, 0x02222222},
141 {REG_A5XX_RBBM_CLOCK_CNTL_SP2, 0x02222222},
142 {REG_A5XX_RBBM_CLOCK_CNTL_SP3, 0x02222222},
143 {REG_A5XX_RBBM_CLOCK_CNTL2_SP0, 0x02222220},
144 {REG_A5XX_RBBM_CLOCK_CNTL2_SP1, 0x02222220},
145 {REG_A5XX_RBBM_CLOCK_CNTL2_SP2, 0x02222220},
146 {REG_A5XX_RBBM_CLOCK_CNTL2_SP3, 0x02222220},
147 {REG_A5XX_RBBM_CLOCK_HYST_SP0, 0x0000F3CF},
148 {REG_A5XX_RBBM_CLOCK_HYST_SP1, 0x0000F3CF},
149 {REG_A5XX_RBBM_CLOCK_HYST_SP2, 0x0000F3CF},
150 {REG_A5XX_RBBM_CLOCK_HYST_SP3, 0x0000F3CF},
151 {REG_A5XX_RBBM_CLOCK_DELAY_SP0, 0x00000080},
152 {REG_A5XX_RBBM_CLOCK_DELAY_SP1, 0x00000080},
153 {REG_A5XX_RBBM_CLOCK_DELAY_SP2, 0x00000080},
154 {REG_A5XX_RBBM_CLOCK_DELAY_SP3, 0x00000080},
155 {REG_A5XX_RBBM_CLOCK_CNTL_TP0, 0x22222222},
156 {REG_A5XX_RBBM_CLOCK_CNTL_TP1, 0x22222222},
157 {REG_A5XX_RBBM_CLOCK_CNTL_TP2, 0x22222222},
158 {REG_A5XX_RBBM_CLOCK_CNTL_TP3, 0x22222222},
159 {REG_A5XX_RBBM_CLOCK_CNTL2_TP0, 0x22222222},
160 {REG_A5XX_RBBM_CLOCK_CNTL2_TP1, 0x22222222},
161 {REG_A5XX_RBBM_CLOCK_CNTL2_TP2, 0x22222222},
162 {REG_A5XX_RBBM_CLOCK_CNTL2_TP3, 0x22222222},
163 {REG_A5XX_RBBM_CLOCK_CNTL3_TP0, 0x00002222},
164 {REG_A5XX_RBBM_CLOCK_CNTL3_TP1, 0x00002222},
165 {REG_A5XX_RBBM_CLOCK_CNTL3_TP2, 0x00002222},
166 {REG_A5XX_RBBM_CLOCK_CNTL3_TP3, 0x00002222},
167 {REG_A5XX_RBBM_CLOCK_HYST_TP0, 0x77777777},
168 {REG_A5XX_RBBM_CLOCK_HYST_TP1, 0x77777777},
169 {REG_A5XX_RBBM_CLOCK_HYST_TP2, 0x77777777},
170 {REG_A5XX_RBBM_CLOCK_HYST_TP3, 0x77777777},
171 {REG_A5XX_RBBM_CLOCK_HYST2_TP0, 0x77777777},
172 {REG_A5XX_RBBM_CLOCK_HYST2_TP1, 0x77777777},
173 {REG_A5XX_RBBM_CLOCK_HYST2_TP2, 0x77777777},
174 {REG_A5XX_RBBM_CLOCK_HYST2_TP3, 0x77777777},
175 {REG_A5XX_RBBM_CLOCK_HYST3_TP0, 0x00007777},
176 {REG_A5XX_RBBM_CLOCK_HYST3_TP1, 0x00007777},
177 {REG_A5XX_RBBM_CLOCK_HYST3_TP2, 0x00007777},
178 {REG_A5XX_RBBM_CLOCK_HYST3_TP3, 0x00007777},
179 {REG_A5XX_RBBM_CLOCK_DELAY_TP0, 0x11111111},
180 {REG_A5XX_RBBM_CLOCK_DELAY_TP1, 0x11111111},
181 {REG_A5XX_RBBM_CLOCK_DELAY_TP2, 0x11111111},
182 {REG_A5XX_RBBM_CLOCK_DELAY_TP3, 0x11111111},
183 {REG_A5XX_RBBM_CLOCK_DELAY2_TP0, 0x11111111},
184 {REG_A5XX_RBBM_CLOCK_DELAY2_TP1, 0x11111111},
185 {REG_A5XX_RBBM_CLOCK_DELAY2_TP2, 0x11111111},
186 {REG_A5XX_RBBM_CLOCK_DELAY2_TP3, 0x11111111},
187 {REG_A5XX_RBBM_CLOCK_DELAY3_TP0, 0x00001111},
188 {REG_A5XX_RBBM_CLOCK_DELAY3_TP1, 0x00001111},
189 {REG_A5XX_RBBM_CLOCK_DELAY3_TP2, 0x00001111},
190 {REG_A5XX_RBBM_CLOCK_DELAY3_TP3, 0x00001111},
191 {REG_A5XX_RBBM_CLOCK_CNTL_UCHE, 0x22222222},
192 {REG_A5XX_RBBM_CLOCK_CNTL2_UCHE, 0x22222222},
193 {REG_A5XX_RBBM_CLOCK_CNTL3_UCHE, 0x22222222},
194 {REG_A5XX_RBBM_CLOCK_CNTL4_UCHE, 0x00222222},
195 {REG_A5XX_RBBM_CLOCK_HYST_UCHE, 0x00444444},
196 {REG_A5XX_RBBM_CLOCK_DELAY_UCHE, 0x00000002},
197 {REG_A5XX_RBBM_CLOCK_CNTL_RB0, 0x22222222},
198 {REG_A5XX_RBBM_CLOCK_CNTL_RB1, 0x22222222},
199 {REG_A5XX_RBBM_CLOCK_CNTL_RB2, 0x22222222},
200 {REG_A5XX_RBBM_CLOCK_CNTL_RB3, 0x22222222},
201 {REG_A5XX_RBBM_CLOCK_CNTL2_RB0, 0x00222222},
202 {REG_A5XX_RBBM_CLOCK_CNTL2_RB1, 0x00222222},
203 {REG_A5XX_RBBM_CLOCK_CNTL2_RB2, 0x00222222},
204 {REG_A5XX_RBBM_CLOCK_CNTL2_RB3, 0x00222222},
205 {REG_A5XX_RBBM_CLOCK_CNTL_CCU0, 0x00022220},
206 {REG_A5XX_RBBM_CLOCK_CNTL_CCU1, 0x00022220},
207 {REG_A5XX_RBBM_CLOCK_CNTL_CCU2, 0x00022220},
208 {REG_A5XX_RBBM_CLOCK_CNTL_CCU3, 0x00022220},
209 {REG_A5XX_RBBM_CLOCK_CNTL_RAC, 0x05522222},
210 {REG_A5XX_RBBM_CLOCK_CNTL2_RAC, 0x00505555},
211 {REG_A5XX_RBBM_CLOCK_HYST_RB_CCU0, 0x04040404},
212 {REG_A5XX_RBBM_CLOCK_HYST_RB_CCU1, 0x04040404},
213 {REG_A5XX_RBBM_CLOCK_HYST_RB_CCU2, 0x04040404},
214 {REG_A5XX_RBBM_CLOCK_HYST_RB_CCU3, 0x04040404},
215 {REG_A5XX_RBBM_CLOCK_HYST_RAC, 0x07444044},
216 {REG_A5XX_RBBM_CLOCK_DELAY_RB_CCU_L1_0, 0x00000002},
217 {REG_A5XX_RBBM_CLOCK_DELAY_RB_CCU_L1_1, 0x00000002},
218 {REG_A5XX_RBBM_CLOCK_DELAY_RB_CCU_L1_2, 0x00000002},
219 {REG_A5XX_RBBM_CLOCK_DELAY_RB_CCU_L1_3, 0x00000002},
220 {REG_A5XX_RBBM_CLOCK_DELAY_RAC, 0x00010011},
221 {REG_A5XX_RBBM_CLOCK_CNTL_TSE_RAS_RBBM, 0x04222222},
222 {REG_A5XX_RBBM_CLOCK_MODE_GPC, 0x02222222},
223 {REG_A5XX_RBBM_CLOCK_MODE_VFD, 0x00002222},
224 {REG_A5XX_RBBM_CLOCK_HYST_TSE_RAS_RBBM, 0x00000000},
225 {REG_A5XX_RBBM_CLOCK_HYST_GPC, 0x04104004},
226 {REG_A5XX_RBBM_CLOCK_HYST_VFD, 0x00000000},
227 {REG_A5XX_RBBM_CLOCK_DELAY_HLSQ, 0x00000000},
228 {REG_A5XX_RBBM_CLOCK_DELAY_TSE_RAS_RBBM, 0x00004000},
229 {REG_A5XX_RBBM_CLOCK_DELAY_GPC, 0x00000200},
230 {REG_A5XX_RBBM_CLOCK_DELAY_VFD, 0x00002222}
231};
232
Jordan Crouse6e749e52017-07-27 10:42:31 -0600233void a5xx_set_hwcg(struct msm_gpu *gpu, bool state)
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700234{
235 unsigned int i;
236
Jordan Crouse6e749e52017-07-27 10:42:31 -0600237 for (i = 0; i < ARRAY_SIZE(a5xx_hwcg); i++)
238 gpu_write(gpu, a5xx_hwcg[i].offset,
239 state ? a5xx_hwcg[i].value : 0);
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700240
Jordan Crouse6e749e52017-07-27 10:42:31 -0600241 gpu_write(gpu, REG_A5XX_RBBM_CLOCK_CNTL, state ? 0xAAA8AA00 : 0);
242 gpu_write(gpu, REG_A5XX_RBBM_ISDB_CNT, state ? 0x182 : 0x180);
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700243}
244
245static int a5xx_me_init(struct msm_gpu *gpu)
246{
247 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
248 struct msm_ringbuffer *ring = gpu->rb;
249
250 OUT_PKT7(ring, CP_ME_INIT, 8);
251
252 OUT_RING(ring, 0x0000002F);
253
254 /* Enable multiple hardware contexts */
255 OUT_RING(ring, 0x00000003);
256
257 /* Enable error detection */
258 OUT_RING(ring, 0x20000000);
259
260 /* Don't enable header dump */
261 OUT_RING(ring, 0x00000000);
262 OUT_RING(ring, 0x00000000);
263
264 /* Specify workarounds for various microcode issues */
265 if (adreno_is_a530(adreno_gpu)) {
266 /* Workaround for token end syncs
267 * Force a WFI after every direct-render 3D mode draw and every
268 * 2D mode 3 draw
269 */
270 OUT_RING(ring, 0x0000000B);
271 } else {
272 /* No workarounds enabled */
273 OUT_RING(ring, 0x00000000);
274 }
275
276 OUT_RING(ring, 0x00000000);
277 OUT_RING(ring, 0x00000000);
278
279 gpu->funcs->flush(gpu);
280
Jordan Crousee895c7b2017-05-08 14:35:00 -0600281 return a5xx_idle(gpu) ? 0 : -EINVAL;
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700282}
283
284static struct drm_gem_object *a5xx_ucode_load_bo(struct msm_gpu *gpu,
285 const struct firmware *fw, u64 *iova)
286{
287 struct drm_device *drm = gpu->dev;
288 struct drm_gem_object *bo;
289 void *ptr;
290
Sushmita Susheelendra0e082702017-06-13 16:52:54 -0600291 bo = msm_gem_new_locked(drm, fw->size - 4, MSM_BO_UNCACHED);
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700292 if (IS_ERR(bo))
293 return bo;
294
Sushmita Susheelendra0e082702017-06-13 16:52:54 -0600295 ptr = msm_gem_get_vaddr(bo);
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700296 if (!ptr) {
Rob Clarkcb1e3812017-06-13 09:15:36 -0400297 drm_gem_object_unreference(bo);
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700298 return ERR_PTR(-ENOMEM);
299 }
300
301 if (iova) {
Sushmita Susheelendra0e082702017-06-13 16:52:54 -0600302 int ret = msm_gem_get_iova(bo, gpu->aspace, iova);
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700303
304 if (ret) {
Rob Clarkcb1e3812017-06-13 09:15:36 -0400305 drm_gem_object_unreference(bo);
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700306 return ERR_PTR(ret);
307 }
308 }
309
310 memcpy(ptr, &fw->data[4], fw->size - 4);
311
Sushmita Susheelendra0e082702017-06-13 16:52:54 -0600312 msm_gem_put_vaddr(bo);
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700313 return bo;
314}
315
316static int a5xx_ucode_init(struct msm_gpu *gpu)
317{
318 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
319 struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu);
320 int ret;
321
322 if (!a5xx_gpu->pm4_bo) {
323 a5xx_gpu->pm4_bo = a5xx_ucode_load_bo(gpu, adreno_gpu->pm4,
324 &a5xx_gpu->pm4_iova);
325
326 if (IS_ERR(a5xx_gpu->pm4_bo)) {
327 ret = PTR_ERR(a5xx_gpu->pm4_bo);
328 a5xx_gpu->pm4_bo = NULL;
329 dev_err(gpu->dev->dev, "could not allocate PM4: %d\n",
330 ret);
331 return ret;
332 }
333 }
334
335 if (!a5xx_gpu->pfp_bo) {
336 a5xx_gpu->pfp_bo = a5xx_ucode_load_bo(gpu, adreno_gpu->pfp,
337 &a5xx_gpu->pfp_iova);
338
339 if (IS_ERR(a5xx_gpu->pfp_bo)) {
340 ret = PTR_ERR(a5xx_gpu->pfp_bo);
341 a5xx_gpu->pfp_bo = NULL;
342 dev_err(gpu->dev->dev, "could not allocate PFP: %d\n",
343 ret);
344 return ret;
345 }
346 }
347
348 gpu_write64(gpu, REG_A5XX_CP_ME_INSTR_BASE_LO,
349 REG_A5XX_CP_ME_INSTR_BASE_HI, a5xx_gpu->pm4_iova);
350
351 gpu_write64(gpu, REG_A5XX_CP_PFP_INSTR_BASE_LO,
352 REG_A5XX_CP_PFP_INSTR_BASE_HI, a5xx_gpu->pfp_iova);
353
354 return 0;
355}
356
Jordan Crouse7c658172017-05-17 08:45:29 -0600357#define SCM_GPU_ZAP_SHADER_RESUME 0
358
359static int a5xx_zap_shader_resume(struct msm_gpu *gpu)
360{
361 int ret;
362
363 ret = qcom_scm_set_remote_state(SCM_GPU_ZAP_SHADER_RESUME, GPU_PAS_ID);
364 if (ret)
365 DRM_ERROR("%s: zap-shader resume failed: %d\n",
366 gpu->name, ret);
367
368 return ret;
369}
370
Jordan Crouse7c658172017-05-17 08:45:29 -0600371static int a5xx_zap_shader_init(struct msm_gpu *gpu)
372{
373 static bool loaded;
374 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
375 struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu);
Jordan Crouse8d6f0822017-07-27 10:42:33 -0600376 struct platform_device *pdev = gpu->pdev;
Jordan Crouse7c658172017-05-17 08:45:29 -0600377 int ret;
378
379 /*
380 * If the zap shader is already loaded into memory we just need to kick
381 * the remote processor to reinitialize it
382 */
383 if (loaded)
384 return a5xx_zap_shader_resume(gpu);
385
386 /* We need SCM to be able to load the firmware */
387 if (!qcom_scm_is_available()) {
388 DRM_DEV_ERROR(&pdev->dev, "SCM is not available\n");
389 return -EPROBE_DEFER;
390 }
391
392 /* Each GPU has a target specific zap shader firmware name to use */
393 if (!adreno_gpu->info->zapfw) {
394 DRM_DEV_ERROR(&pdev->dev,
395 "Zap shader firmware file not specified for this target\n");
396 return -ENODEV;
397 }
398
Arnd Bergmann8f93e042017-07-26 21:59:21 +0200399 ret = zap_shader_load_mdt(&pdev->dev, adreno_gpu->info->zapfw);
Jordan Crouse7c658172017-05-17 08:45:29 -0600400
401 loaded = !ret;
402
403 return ret;
404}
405
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700406#define A5XX_INT_MASK (A5XX_RBBM_INT_0_MASK_RBBM_AHB_ERROR | \
407 A5XX_RBBM_INT_0_MASK_RBBM_TRANSFER_TIMEOUT | \
408 A5XX_RBBM_INT_0_MASK_RBBM_ME_MS_TIMEOUT | \
409 A5XX_RBBM_INT_0_MASK_RBBM_PFP_MS_TIMEOUT | \
410 A5XX_RBBM_INT_0_MASK_RBBM_ETS_MS_TIMEOUT | \
411 A5XX_RBBM_INT_0_MASK_RBBM_ATB_ASYNC_OVERFLOW | \
412 A5XX_RBBM_INT_0_MASK_CP_HW_ERROR | \
Jordan Crouseac1b5ab2017-07-27 10:42:36 -0600413 A5XX_RBBM_INT_0_MASK_MISC_HANG_DETECT | \
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700414 A5XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS | \
415 A5XX_RBBM_INT_0_MASK_UCHE_OOB_ACCESS | \
416 A5XX_RBBM_INT_0_MASK_GPMU_VOLTAGE_DROOP)
417
418static int a5xx_hw_init(struct msm_gpu *gpu)
419{
420 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
421 int ret;
422
423 gpu_write(gpu, REG_A5XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x00000003);
424
425 /* Make all blocks contribute to the GPU BUSY perf counter */
426 gpu_write(gpu, REG_A5XX_RBBM_PERFCTR_GPU_BUSY_MASKED, 0xFFFFFFFF);
427
428 /* Enable RBBM error reporting bits */
429 gpu_write(gpu, REG_A5XX_RBBM_AHB_CNTL0, 0x00000001);
430
Rob Clark4e09b952017-01-30 11:15:14 -0500431 if (adreno_gpu->info->quirks & ADRENO_QUIRK_FAULT_DETECT_MASK) {
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700432 /*
433 * Mask out the activity signals from RB1-3 to avoid false
434 * positives
435 */
436
437 gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL11,
438 0xF0000000);
439 gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL12,
440 0xFFFFFFFF);
441 gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL13,
442 0xFFFFFFFF);
443 gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL14,
444 0xFFFFFFFF);
445 gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL15,
446 0xFFFFFFFF);
447 gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL16,
448 0xFFFFFFFF);
449 gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL17,
450 0xFFFFFFFF);
451 gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL18,
452 0xFFFFFFFF);
453 }
454
455 /* Enable fault detection */
456 gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_INT_CNTL,
457 (1 << 30) | 0xFFFF);
458
459 /* Turn on performance counters */
460 gpu_write(gpu, REG_A5XX_RBBM_PERFCTR_CNTL, 0x01);
461
462 /* Increase VFD cache access so LRZ and other data gets evicted less */
463 gpu_write(gpu, REG_A5XX_UCHE_CACHE_WAYS, 0x02);
464
465 /* Disable L2 bypass in the UCHE */
466 gpu_write(gpu, REG_A5XX_UCHE_TRAP_BASE_LO, 0xFFFF0000);
467 gpu_write(gpu, REG_A5XX_UCHE_TRAP_BASE_HI, 0x0001FFFF);
468 gpu_write(gpu, REG_A5XX_UCHE_WRITE_THRU_BASE_LO, 0xFFFF0000);
469 gpu_write(gpu, REG_A5XX_UCHE_WRITE_THRU_BASE_HI, 0x0001FFFF);
470
471 /* Set the GMEM VA range (0 to gpu->gmem) */
472 gpu_write(gpu, REG_A5XX_UCHE_GMEM_RANGE_MIN_LO, 0x00100000);
473 gpu_write(gpu, REG_A5XX_UCHE_GMEM_RANGE_MIN_HI, 0x00000000);
474 gpu_write(gpu, REG_A5XX_UCHE_GMEM_RANGE_MAX_LO,
475 0x00100000 + adreno_gpu->gmem - 1);
476 gpu_write(gpu, REG_A5XX_UCHE_GMEM_RANGE_MAX_HI, 0x00000000);
477
478 gpu_write(gpu, REG_A5XX_CP_MEQ_THRESHOLDS, 0x40);
479 gpu_write(gpu, REG_A5XX_CP_MERCIU_SIZE, 0x40);
480 gpu_write(gpu, REG_A5XX_CP_ROQ_THRESHOLDS_2, 0x80000060);
481 gpu_write(gpu, REG_A5XX_CP_ROQ_THRESHOLDS_1, 0x40201B16);
482
483 gpu_write(gpu, REG_A5XX_PC_DBG_ECO_CNTL, (0x400 << 11 | 0x300 << 22));
484
Rob Clark4e09b952017-01-30 11:15:14 -0500485 if (adreno_gpu->info->quirks & ADRENO_QUIRK_TWO_PASS_USE_WFI)
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700486 gpu_rmw(gpu, REG_A5XX_PC_DBG_ECO_CNTL, 0, (1 << 8));
487
488 gpu_write(gpu, REG_A5XX_PC_DBG_ECO_CNTL, 0xc0200100);
489
490 /* Enable USE_RETENTION_FLOPS */
491 gpu_write(gpu, REG_A5XX_CP_CHICKEN_DBG, 0x02000000);
492
493 /* Enable ME/PFP split notification */
494 gpu_write(gpu, REG_A5XX_RBBM_AHB_CNTL1, 0xA6FFFFFF);
495
496 /* Enable HWCG */
Jordan Crouse6e749e52017-07-27 10:42:31 -0600497 a5xx_set_hwcg(gpu, true);
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700498
499 gpu_write(gpu, REG_A5XX_RBBM_AHB_CNTL2, 0x0000003F);
500
501 /* Set the highest bank bit */
502 gpu_write(gpu, REG_A5XX_TPL1_MODE_CNTL, 2 << 7);
503 gpu_write(gpu, REG_A5XX_RB_MODE_CNTL, 2 << 1);
504
505 /* Protect registers from the CP */
506 gpu_write(gpu, REG_A5XX_CP_PROTECT_CNTL, 0x00000007);
507
508 /* RBBM */
509 gpu_write(gpu, REG_A5XX_CP_PROTECT(0), ADRENO_PROTECT_RW(0x04, 4));
510 gpu_write(gpu, REG_A5XX_CP_PROTECT(1), ADRENO_PROTECT_RW(0x08, 8));
511 gpu_write(gpu, REG_A5XX_CP_PROTECT(2), ADRENO_PROTECT_RW(0x10, 16));
512 gpu_write(gpu, REG_A5XX_CP_PROTECT(3), ADRENO_PROTECT_RW(0x20, 32));
513 gpu_write(gpu, REG_A5XX_CP_PROTECT(4), ADRENO_PROTECT_RW(0x40, 64));
514 gpu_write(gpu, REG_A5XX_CP_PROTECT(5), ADRENO_PROTECT_RW(0x80, 64));
515
516 /* Content protect */
517 gpu_write(gpu, REG_A5XX_CP_PROTECT(6),
518 ADRENO_PROTECT_RW(REG_A5XX_RBBM_SECVID_TSB_TRUSTED_BASE_LO,
519 16));
520 gpu_write(gpu, REG_A5XX_CP_PROTECT(7),
521 ADRENO_PROTECT_RW(REG_A5XX_RBBM_SECVID_TRUST_CNTL, 2));
522
523 /* CP */
524 gpu_write(gpu, REG_A5XX_CP_PROTECT(8), ADRENO_PROTECT_RW(0x800, 64));
525 gpu_write(gpu, REG_A5XX_CP_PROTECT(9), ADRENO_PROTECT_RW(0x840, 8));
526 gpu_write(gpu, REG_A5XX_CP_PROTECT(10), ADRENO_PROTECT_RW(0x880, 32));
527 gpu_write(gpu, REG_A5XX_CP_PROTECT(11), ADRENO_PROTECT_RW(0xAA0, 1));
528
529 /* RB */
530 gpu_write(gpu, REG_A5XX_CP_PROTECT(12), ADRENO_PROTECT_RW(0xCC0, 1));
531 gpu_write(gpu, REG_A5XX_CP_PROTECT(13), ADRENO_PROTECT_RW(0xCF0, 2));
532
533 /* VPC */
534 gpu_write(gpu, REG_A5XX_CP_PROTECT(14), ADRENO_PROTECT_RW(0xE68, 8));
535 gpu_write(gpu, REG_A5XX_CP_PROTECT(15), ADRENO_PROTECT_RW(0xE70, 4));
536
537 /* UCHE */
538 gpu_write(gpu, REG_A5XX_CP_PROTECT(16), ADRENO_PROTECT_RW(0xE80, 16));
539
540 if (adreno_is_a530(adreno_gpu))
541 gpu_write(gpu, REG_A5XX_CP_PROTECT(17),
542 ADRENO_PROTECT_RW(0x10000, 0x8000));
543
544 gpu_write(gpu, REG_A5XX_RBBM_SECVID_TSB_CNTL, 0);
545 /*
546 * Disable the trusted memory range - we don't actually supported secure
547 * memory rendering at this point in time and we don't want to block off
548 * part of the virtual memory space.
549 */
550 gpu_write64(gpu, REG_A5XX_RBBM_SECVID_TSB_TRUSTED_BASE_LO,
551 REG_A5XX_RBBM_SECVID_TSB_TRUSTED_BASE_HI, 0x00000000);
552 gpu_write(gpu, REG_A5XX_RBBM_SECVID_TSB_TRUSTED_SIZE, 0x00000000);
553
Jordan Crouse2401a002016-11-28 12:28:34 -0700554 /* Load the GPMU firmware before starting the HW init */
555 a5xx_gpmu_ucode_init(gpu);
556
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700557 ret = adreno_hw_init(gpu);
558 if (ret)
559 return ret;
560
561 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)) {
583 OUT_PKT7(gpu->rb, CP_EVENT_WRITE, 1);
584 OUT_RING(gpu->rb, 0x0F);
585
586 gpu->funcs->flush(gpu);
Jordan Crousee895c7b2017-05-08 14:35:00 -0600587 if (!a5xx_idle(gpu))
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) {
600 OUT_PKT7(gpu->rb, CP_SET_SECURE_MODE, 1);
601 OUT_RING(gpu->rb, 0x00000000);
602
603 gpu->funcs->flush(gpu);
Jordan Crousee895c7b2017-05-08 14:35:00 -0600604 if (!a5xx_idle(gpu))
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 Crousee895c7b2017-05-08 14:35:00 -0600678bool a5xx_idle(struct msm_gpu *gpu)
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700679{
680 /* wait for CP to drain ringbuffer: */
681 if (!adreno_idle(gpu))
682 return false;
683
684 if (spin_until(_a5xx_check_idle(gpu))) {
685 DRM_ERROR("%s: %ps: timeout waiting for GPU to idle: status %8.8X irq %8.8X\n",
686 gpu->name, __builtin_return_address(0),
687 gpu_read(gpu, REG_A5XX_RBBM_STATUS),
688 gpu_read(gpu, REG_A5XX_RBBM_INT_0_STATUS));
689
690 return false;
691 }
692
693 return true;
694}
695
Rob Clark7f8036b2016-12-07 11:13:53 -0500696static int a5xx_fault_handler(void *arg, unsigned long iova, int flags)
697{
698 struct msm_gpu *gpu = arg;
699 pr_warn_ratelimited("*** gpu fault: iova=%08lx, flags=%d (%u,%u,%u,%u)\n",
700 iova, flags,
701 gpu_read(gpu, REG_A5XX_CP_SCRATCH_REG(4)),
702 gpu_read(gpu, REG_A5XX_CP_SCRATCH_REG(5)),
703 gpu_read(gpu, REG_A5XX_CP_SCRATCH_REG(6)),
704 gpu_read(gpu, REG_A5XX_CP_SCRATCH_REG(7)));
705
706 return -EFAULT;
707}
708
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700709static void a5xx_cp_err_irq(struct msm_gpu *gpu)
710{
711 u32 status = gpu_read(gpu, REG_A5XX_CP_INTERRUPT_STATUS);
712
713 if (status & A5XX_CP_INT_CP_OPCODE_ERROR) {
714 u32 val;
715
716 gpu_write(gpu, REG_A5XX_CP_PFP_STAT_ADDR, 0);
717
718 /*
719 * REG_A5XX_CP_PFP_STAT_DATA is indexed, and we want index 1 so
720 * read it twice
721 */
722
723 gpu_read(gpu, REG_A5XX_CP_PFP_STAT_DATA);
724 val = gpu_read(gpu, REG_A5XX_CP_PFP_STAT_DATA);
725
726 dev_err_ratelimited(gpu->dev->dev, "CP | opcode error | possible opcode=0x%8.8X\n",
727 val);
728 }
729
730 if (status & A5XX_CP_INT_CP_HW_FAULT_ERROR)
731 dev_err_ratelimited(gpu->dev->dev, "CP | HW fault | status=0x%8.8X\n",
732 gpu_read(gpu, REG_A5XX_CP_HW_FAULT));
733
734 if (status & A5XX_CP_INT_CP_DMA_ERROR)
735 dev_err_ratelimited(gpu->dev->dev, "CP | DMA error\n");
736
737 if (status & A5XX_CP_INT_CP_REGISTER_PROTECTION_ERROR) {
738 u32 val = gpu_read(gpu, REG_A5XX_CP_PROTECT_STATUS);
739
740 dev_err_ratelimited(gpu->dev->dev,
741 "CP | protected mode error | %s | addr=0x%8.8X | status=0x%8.8X\n",
742 val & (1 << 24) ? "WRITE" : "READ",
743 (val & 0xFFFFF) >> 2, val);
744 }
745
746 if (status & A5XX_CP_INT_CP_AHB_ERROR) {
747 u32 status = gpu_read(gpu, REG_A5XX_CP_AHB_FAULT);
748 const char *access[16] = { "reserved", "reserved",
749 "timestamp lo", "timestamp hi", "pfp read", "pfp write",
750 "", "", "me read", "me write", "", "", "crashdump read",
751 "crashdump write" };
752
753 dev_err_ratelimited(gpu->dev->dev,
754 "CP | AHB error | addr=%X access=%s error=%d | status=0x%8.8X\n",
755 status & 0xFFFFF, access[(status >> 24) & 0xF],
756 (status & (1 << 31)), status);
757 }
758}
759
Jordan Crouse7352fb52017-03-07 09:50:29 -0700760static void a5xx_rbbm_err_irq(struct msm_gpu *gpu, u32 status)
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700761{
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700762 if (status & A5XX_RBBM_INT_0_MASK_RBBM_AHB_ERROR) {
763 u32 val = gpu_read(gpu, REG_A5XX_RBBM_AHB_ERROR_STATUS);
764
765 dev_err_ratelimited(gpu->dev->dev,
766 "RBBM | AHB bus error | %s | addr=0x%X | ports=0x%X:0x%X\n",
767 val & (1 << 28) ? "WRITE" : "READ",
768 (val & 0xFFFFF) >> 2, (val >> 20) & 0x3,
769 (val >> 24) & 0xF);
770
771 /* Clear the error */
772 gpu_write(gpu, REG_A5XX_RBBM_AHB_CMD, (1 << 4));
Jordan Crouse7352fb52017-03-07 09:50:29 -0700773
774 /* Clear the interrupt */
775 gpu_write(gpu, REG_A5XX_RBBM_INT_CLEAR_CMD,
776 A5XX_RBBM_INT_0_MASK_RBBM_AHB_ERROR);
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700777 }
778
779 if (status & A5XX_RBBM_INT_0_MASK_RBBM_TRANSFER_TIMEOUT)
780 dev_err_ratelimited(gpu->dev->dev, "RBBM | AHB transfer timeout\n");
781
782 if (status & A5XX_RBBM_INT_0_MASK_RBBM_ME_MS_TIMEOUT)
783 dev_err_ratelimited(gpu->dev->dev, "RBBM | ME master split | status=0x%X\n",
784 gpu_read(gpu, REG_A5XX_RBBM_AHB_ME_SPLIT_STATUS));
785
786 if (status & A5XX_RBBM_INT_0_MASK_RBBM_PFP_MS_TIMEOUT)
787 dev_err_ratelimited(gpu->dev->dev, "RBBM | PFP master split | status=0x%X\n",
788 gpu_read(gpu, REG_A5XX_RBBM_AHB_PFP_SPLIT_STATUS));
789
790 if (status & A5XX_RBBM_INT_0_MASK_RBBM_ETS_MS_TIMEOUT)
791 dev_err_ratelimited(gpu->dev->dev, "RBBM | ETS master split | status=0x%X\n",
792 gpu_read(gpu, REG_A5XX_RBBM_AHB_ETS_SPLIT_STATUS));
793
794 if (status & A5XX_RBBM_INT_0_MASK_RBBM_ATB_ASYNC_OVERFLOW)
795 dev_err_ratelimited(gpu->dev->dev, "RBBM | ATB ASYNC overflow\n");
796
797 if (status & A5XX_RBBM_INT_0_MASK_RBBM_ATB_BUS_OVERFLOW)
798 dev_err_ratelimited(gpu->dev->dev, "RBBM | ATB bus overflow\n");
799}
800
801static void a5xx_uche_err_irq(struct msm_gpu *gpu)
802{
803 uint64_t addr = (uint64_t) gpu_read(gpu, REG_A5XX_UCHE_TRAP_LOG_HI);
804
805 addr |= gpu_read(gpu, REG_A5XX_UCHE_TRAP_LOG_LO);
806
807 dev_err_ratelimited(gpu->dev->dev, "UCHE | Out of bounds access | addr=0x%llX\n",
808 addr);
809}
810
811static void a5xx_gpmu_err_irq(struct msm_gpu *gpu)
812{
813 dev_err_ratelimited(gpu->dev->dev, "GPMU | voltage droop\n");
814}
815
Jordan Crouseac1b5ab2017-07-27 10:42:36 -0600816static void a5xx_fault_detect_irq(struct msm_gpu *gpu)
817{
818 struct drm_device *dev = gpu->dev;
819 struct msm_drm_private *priv = dev->dev_private;
Jordan Crouseac1b5ab2017-07-27 10:42:36 -0600820
Jordan Crouse1267a4d2017-07-27 10:42:39 -0600821 dev_err(dev->dev, "gpu fault fence %x status %8.8X rb %4.4x/%4.4x ib1 %16.16llX/%4.4x ib2 %16.16llX/%4.4x\n",
822 gpu->funcs->last_fence(gpu),
Jordan Crouseac1b5ab2017-07-27 10:42:36 -0600823 gpu_read(gpu, REG_A5XX_RBBM_STATUS),
824 gpu_read(gpu, REG_A5XX_CP_RB_RPTR),
825 gpu_read(gpu, REG_A5XX_CP_RB_WPTR),
826 gpu_read64(gpu, REG_A5XX_CP_IB1_BASE, REG_A5XX_CP_IB1_BASE_HI),
827 gpu_read(gpu, REG_A5XX_CP_IB1_BUFSZ),
828 gpu_read64(gpu, REG_A5XX_CP_IB2_BASE, REG_A5XX_CP_IB2_BASE_HI),
829 gpu_read(gpu, REG_A5XX_CP_IB2_BUFSZ));
830
831 /* Turn off the hangcheck timer to keep it from bothering us */
832 del_timer(&gpu->hangcheck_timer);
833
834 queue_work(priv->wq, &gpu->recover_work);
835}
836
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700837#define RBBM_ERROR_MASK \
838 (A5XX_RBBM_INT_0_MASK_RBBM_AHB_ERROR | \
839 A5XX_RBBM_INT_0_MASK_RBBM_TRANSFER_TIMEOUT | \
840 A5XX_RBBM_INT_0_MASK_RBBM_ME_MS_TIMEOUT | \
841 A5XX_RBBM_INT_0_MASK_RBBM_PFP_MS_TIMEOUT | \
842 A5XX_RBBM_INT_0_MASK_RBBM_ETS_MS_TIMEOUT | \
843 A5XX_RBBM_INT_0_MASK_RBBM_ATB_ASYNC_OVERFLOW)
844
845static irqreturn_t a5xx_irq(struct msm_gpu *gpu)
846{
847 u32 status = gpu_read(gpu, REG_A5XX_RBBM_INT_0_STATUS);
848
Jordan Crouse7352fb52017-03-07 09:50:29 -0700849 /*
850 * Clear all the interrupts except RBBM_AHB_ERROR - if we clear it
851 * before the source is cleared the interrupt will storm.
852 */
853 gpu_write(gpu, REG_A5XX_RBBM_INT_CLEAR_CMD,
854 status & ~A5XX_RBBM_INT_0_MASK_RBBM_AHB_ERROR);
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700855
Jordan Crouse7352fb52017-03-07 09:50:29 -0700856 /* Pass status to a5xx_rbbm_err_irq because we've already cleared it */
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700857 if (status & RBBM_ERROR_MASK)
Jordan Crouse7352fb52017-03-07 09:50:29 -0700858 a5xx_rbbm_err_irq(gpu, status);
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700859
860 if (status & A5XX_RBBM_INT_0_MASK_CP_HW_ERROR)
861 a5xx_cp_err_irq(gpu);
862
Jordan Crouseac1b5ab2017-07-27 10:42:36 -0600863 if (status & A5XX_RBBM_INT_0_MASK_MISC_HANG_DETECT)
864 a5xx_fault_detect_irq(gpu);
865
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700866 if (status & A5XX_RBBM_INT_0_MASK_UCHE_OOB_ACCESS)
867 a5xx_uche_err_irq(gpu);
868
869 if (status & A5XX_RBBM_INT_0_MASK_GPMU_VOLTAGE_DROOP)
870 a5xx_gpmu_err_irq(gpu);
871
872 if (status & A5XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS)
873 msm_gpu_retire(gpu);
874
875 return IRQ_HANDLED;
876}
877
878static const u32 a5xx_register_offsets[REG_ADRENO_REGISTER_MAX] = {
879 REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_BASE, REG_A5XX_CP_RB_BASE),
880 REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_BASE_HI, REG_A5XX_CP_RB_BASE_HI),
881 REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_RPTR_ADDR, REG_A5XX_CP_RB_RPTR_ADDR),
882 REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_RPTR_ADDR_HI,
883 REG_A5XX_CP_RB_RPTR_ADDR_HI),
884 REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_RPTR, REG_A5XX_CP_RB_RPTR),
885 REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_WPTR, REG_A5XX_CP_RB_WPTR),
886 REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_CNTL, REG_A5XX_CP_RB_CNTL),
887};
888
889static const u32 a5xx_registers[] = {
890 0x0000, 0x0002, 0x0004, 0x0020, 0x0022, 0x0026, 0x0029, 0x002B,
891 0x002E, 0x0035, 0x0038, 0x0042, 0x0044, 0x0044, 0x0047, 0x0095,
892 0x0097, 0x00BB, 0x03A0, 0x0464, 0x0469, 0x046F, 0x04D2, 0x04D3,
Jordan Crouse3394f562017-07-27 10:42:30 -0600893 0x04E0, 0x0533, 0x0540, 0x0555, 0x0800, 0x081A, 0x081F, 0x0841,
894 0x0860, 0x0860, 0x0880, 0x08A0, 0x0B00, 0x0B12, 0x0B15, 0x0B28,
895 0x0B78, 0x0B7F, 0x0BB0, 0x0BBD, 0x0BC0, 0x0BC6, 0x0BD0, 0x0C53,
896 0x0C60, 0x0C61, 0x0C80, 0x0C82, 0x0C84, 0x0C85, 0x0C90, 0x0C98,
897 0x0CA0, 0x0CA0, 0x0CB0, 0x0CB2, 0x2180, 0x2185, 0x2580, 0x2585,
898 0x0CC1, 0x0CC1, 0x0CC4, 0x0CC7, 0x0CCC, 0x0CCC, 0x0CD0, 0x0CD8,
899 0x0CE0, 0x0CE5, 0x0CE8, 0x0CE8, 0x0CEC, 0x0CF1, 0x0CFB, 0x0D0E,
900 0x2100, 0x211E, 0x2140, 0x2145, 0x2500, 0x251E, 0x2540, 0x2545,
901 0x0D10, 0x0D17, 0x0D20, 0x0D23, 0x0D30, 0x0D30, 0x20C0, 0x20C0,
902 0x24C0, 0x24C0, 0x0E40, 0x0E43, 0x0E4A, 0x0E4A, 0x0E50, 0x0E57,
903 0x0E60, 0x0E7C, 0x0E80, 0x0E8E, 0x0E90, 0x0E96, 0x0EA0, 0x0EA8,
904 0x0EB0, 0x0EB2, 0xE140, 0xE147, 0xE150, 0xE187, 0xE1A0, 0xE1A9,
905 0xE1B0, 0xE1B6, 0xE1C0, 0xE1C7, 0xE1D0, 0xE1D1, 0xE200, 0xE201,
906 0xE210, 0xE21C, 0xE240, 0xE268, 0xE000, 0xE006, 0xE010, 0xE09A,
907 0xE0A0, 0xE0A4, 0xE0AA, 0xE0EB, 0xE100, 0xE105, 0xE380, 0xE38F,
908 0xE3B0, 0xE3B0, 0xE400, 0xE405, 0xE408, 0xE4E9, 0xE4F0, 0xE4F0,
909 0xE280, 0xE280, 0xE282, 0xE2A3, 0xE2A5, 0xE2C2, 0xE940, 0xE947,
910 0xE950, 0xE987, 0xE9A0, 0xE9A9, 0xE9B0, 0xE9B6, 0xE9C0, 0xE9C7,
911 0xE9D0, 0xE9D1, 0xEA00, 0xEA01, 0xEA10, 0xEA1C, 0xEA40, 0xEA68,
912 0xE800, 0xE806, 0xE810, 0xE89A, 0xE8A0, 0xE8A4, 0xE8AA, 0xE8EB,
913 0xE900, 0xE905, 0xEB80, 0xEB8F, 0xEBB0, 0xEBB0, 0xEC00, 0xEC05,
914 0xEC08, 0xECE9, 0xECF0, 0xECF0, 0xEA80, 0xEA80, 0xEA82, 0xEAA3,
915 0xEAA5, 0xEAC2, 0xA800, 0xA8FF, 0xAC60, 0xAC60, 0xB000, 0xB97F,
916 0xB9A0, 0xB9BF, ~0
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700917};
918
919static void a5xx_dump(struct msm_gpu *gpu)
920{
921 dev_info(gpu->dev->dev, "status: %08x\n",
922 gpu_read(gpu, REG_A5XX_RBBM_STATUS));
923 adreno_dump(gpu);
924}
925
926static int a5xx_pm_resume(struct msm_gpu *gpu)
927{
Jordan Crouse2401a002016-11-28 12:28:34 -0700928 int ret;
929
930 /* Turn on the core power */
931 ret = msm_gpu_pm_resume(gpu);
932 if (ret)
933 return ret;
934
935 /* Turn the RBCCU domain first to limit the chances of voltage droop */
936 gpu_write(gpu, REG_A5XX_GPMU_RBCCU_POWER_CNTL, 0x778000);
937
938 /* Wait 3 usecs before polling */
939 udelay(3);
940
941 ret = spin_usecs(gpu, 20, REG_A5XX_GPMU_RBCCU_PWR_CLK_STATUS,
942 (1 << 20), (1 << 20));
943 if (ret) {
944 DRM_ERROR("%s: timeout waiting for RBCCU GDSC enable: %X\n",
945 gpu->name,
946 gpu_read(gpu, REG_A5XX_GPMU_RBCCU_PWR_CLK_STATUS));
947 return ret;
948 }
949
950 /* Turn on the SP domain */
951 gpu_write(gpu, REG_A5XX_GPMU_SP_POWER_CNTL, 0x778000);
952 ret = spin_usecs(gpu, 20, REG_A5XX_GPMU_SP_PWR_CLK_STATUS,
953 (1 << 20), (1 << 20));
954 if (ret)
955 DRM_ERROR("%s: timeout waiting for SP GDSC enable\n",
956 gpu->name);
957
958 return ret;
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700959}
960
961static int a5xx_pm_suspend(struct msm_gpu *gpu)
962{
Jordan Crouse2401a002016-11-28 12:28:34 -0700963 /* Clear the VBIF pipe before shutting down */
964 gpu_write(gpu, REG_A5XX_VBIF_XIN_HALT_CTRL0, 0xF);
965 spin_until((gpu_read(gpu, REG_A5XX_VBIF_XIN_HALT_CTRL1) & 0xF) == 0xF);
966
967 gpu_write(gpu, REG_A5XX_VBIF_XIN_HALT_CTRL0, 0);
968
969 /*
970 * Reset the VBIF before power collapse to avoid issue with FIFO
971 * entries
972 */
973 gpu_write(gpu, REG_A5XX_RBBM_BLOCK_SW_RESET_CMD, 0x003C0000);
974 gpu_write(gpu, REG_A5XX_RBBM_BLOCK_SW_RESET_CMD, 0x00000000);
975
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700976 return msm_gpu_pm_suspend(gpu);
977}
978
979static int a5xx_get_timestamp(struct msm_gpu *gpu, uint64_t *value)
980{
981 *value = gpu_read64(gpu, REG_A5XX_RBBM_PERFCTR_CP_0_LO,
982 REG_A5XX_RBBM_PERFCTR_CP_0_HI);
983
984 return 0;
985}
986
987#ifdef CONFIG_DEBUG_FS
988static void a5xx_show(struct msm_gpu *gpu, struct seq_file *m)
989{
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700990 seq_printf(m, "status: %08x\n",
991 gpu_read(gpu, REG_A5XX_RBBM_STATUS));
Jordan Crousea23cb3b2017-07-27 10:42:32 -0600992
993 /*
994 * Temporarily disable hardware clock gating before going into
995 * adreno_show to avoid issues while reading the registers
996 */
997 a5xx_set_hwcg(gpu, false);
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700998 adreno_show(gpu, m);
Jordan Crousea23cb3b2017-07-27 10:42:32 -0600999 a5xx_set_hwcg(gpu, true);
Jordan Crouseb5f103a2016-11-28 12:28:33 -07001000}
1001#endif
1002
1003static const struct adreno_gpu_funcs funcs = {
1004 .base = {
1005 .get_param = adreno_get_param,
1006 .hw_init = a5xx_hw_init,
1007 .pm_suspend = a5xx_pm_suspend,
1008 .pm_resume = a5xx_pm_resume,
1009 .recover = a5xx_recover,
1010 .last_fence = adreno_last_fence,
1011 .submit = a5xx_submit,
1012 .flush = adreno_flush,
Jordan Crouseb5f103a2016-11-28 12:28:33 -07001013 .irq = a5xx_irq,
1014 .destroy = a5xx_destroy,
Arnd Bergmann0c3eaf12017-03-13 17:43:48 +01001015#ifdef CONFIG_DEBUG_FS
Jordan Crouseb5f103a2016-11-28 12:28:33 -07001016 .show = a5xx_show,
Arnd Bergmann0c3eaf12017-03-13 17:43:48 +01001017#endif
Jordan Crouseb5f103a2016-11-28 12:28:33 -07001018 },
1019 .get_timestamp = a5xx_get_timestamp,
1020};
1021
1022struct msm_gpu *a5xx_gpu_init(struct drm_device *dev)
1023{
1024 struct msm_drm_private *priv = dev->dev_private;
1025 struct platform_device *pdev = priv->gpu_pdev;
1026 struct a5xx_gpu *a5xx_gpu = NULL;
1027 struct adreno_gpu *adreno_gpu;
1028 struct msm_gpu *gpu;
1029 int ret;
1030
1031 if (!pdev) {
1032 dev_err(dev->dev, "No A5XX device is defined\n");
1033 return ERR_PTR(-ENXIO);
1034 }
1035
1036 a5xx_gpu = kzalloc(sizeof(*a5xx_gpu), GFP_KERNEL);
1037 if (!a5xx_gpu)
1038 return ERR_PTR(-ENOMEM);
1039
1040 adreno_gpu = &a5xx_gpu->base;
1041 gpu = &adreno_gpu->base;
1042
Jordan Crouseb5f103a2016-11-28 12:28:33 -07001043 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}