blob: 1e164008f5b9d1e4a1055f9f1e0f2d3a9ed4f8c1 [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{
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700287 struct drm_gem_object *bo;
288 void *ptr;
289
Jordan Crouse82232862017-07-27 10:42:40 -0600290 ptr = msm_gem_kernel_new_locked(gpu->dev, fw->size - 4,
291 MSM_BO_UNCACHED | MSM_BO_GPU_READONLY, gpu->aspace, &bo, iova);
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700292
Jordan Crouse82232862017-07-27 10:42:40 -0600293 if (IS_ERR(ptr))
294 return ERR_CAST(ptr);
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700295
296 memcpy(ptr, &fw->data[4], fw->size - 4);
297
Sushmita Susheelendra0e082702017-06-13 16:52:54 -0600298 msm_gem_put_vaddr(bo);
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700299 return bo;
300}
301
302static int a5xx_ucode_init(struct msm_gpu *gpu)
303{
304 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
305 struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu);
306 int ret;
307
308 if (!a5xx_gpu->pm4_bo) {
309 a5xx_gpu->pm4_bo = a5xx_ucode_load_bo(gpu, adreno_gpu->pm4,
310 &a5xx_gpu->pm4_iova);
311
312 if (IS_ERR(a5xx_gpu->pm4_bo)) {
313 ret = PTR_ERR(a5xx_gpu->pm4_bo);
314 a5xx_gpu->pm4_bo = NULL;
315 dev_err(gpu->dev->dev, "could not allocate PM4: %d\n",
316 ret);
317 return ret;
318 }
319 }
320
321 if (!a5xx_gpu->pfp_bo) {
322 a5xx_gpu->pfp_bo = a5xx_ucode_load_bo(gpu, adreno_gpu->pfp,
323 &a5xx_gpu->pfp_iova);
324
325 if (IS_ERR(a5xx_gpu->pfp_bo)) {
326 ret = PTR_ERR(a5xx_gpu->pfp_bo);
327 a5xx_gpu->pfp_bo = NULL;
328 dev_err(gpu->dev->dev, "could not allocate PFP: %d\n",
329 ret);
330 return ret;
331 }
332 }
333
334 gpu_write64(gpu, REG_A5XX_CP_ME_INSTR_BASE_LO,
335 REG_A5XX_CP_ME_INSTR_BASE_HI, a5xx_gpu->pm4_iova);
336
337 gpu_write64(gpu, REG_A5XX_CP_PFP_INSTR_BASE_LO,
338 REG_A5XX_CP_PFP_INSTR_BASE_HI, a5xx_gpu->pfp_iova);
339
340 return 0;
341}
342
Jordan Crouse7c658172017-05-17 08:45:29 -0600343#define SCM_GPU_ZAP_SHADER_RESUME 0
344
345static int a5xx_zap_shader_resume(struct msm_gpu *gpu)
346{
347 int ret;
348
349 ret = qcom_scm_set_remote_state(SCM_GPU_ZAP_SHADER_RESUME, GPU_PAS_ID);
350 if (ret)
351 DRM_ERROR("%s: zap-shader resume failed: %d\n",
352 gpu->name, ret);
353
354 return ret;
355}
356
Jordan Crouse7c658172017-05-17 08:45:29 -0600357static int a5xx_zap_shader_init(struct msm_gpu *gpu)
358{
359 static bool loaded;
360 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
361 struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu);
Jordan Crouse8d6f0822017-07-27 10:42:33 -0600362 struct platform_device *pdev = gpu->pdev;
Jordan Crouse7c658172017-05-17 08:45:29 -0600363 int ret;
364
365 /*
366 * If the zap shader is already loaded into memory we just need to kick
367 * the remote processor to reinitialize it
368 */
369 if (loaded)
370 return a5xx_zap_shader_resume(gpu);
371
372 /* We need SCM to be able to load the firmware */
373 if (!qcom_scm_is_available()) {
374 DRM_DEV_ERROR(&pdev->dev, "SCM is not available\n");
375 return -EPROBE_DEFER;
376 }
377
378 /* Each GPU has a target specific zap shader firmware name to use */
379 if (!adreno_gpu->info->zapfw) {
380 DRM_DEV_ERROR(&pdev->dev,
381 "Zap shader firmware file not specified for this target\n");
382 return -ENODEV;
383 }
384
Arnd Bergmann8f93e042017-07-26 21:59:21 +0200385 ret = zap_shader_load_mdt(&pdev->dev, adreno_gpu->info->zapfw);
Jordan Crouse7c658172017-05-17 08:45:29 -0600386
387 loaded = !ret;
388
389 return ret;
390}
391
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700392#define A5XX_INT_MASK (A5XX_RBBM_INT_0_MASK_RBBM_AHB_ERROR | \
393 A5XX_RBBM_INT_0_MASK_RBBM_TRANSFER_TIMEOUT | \
394 A5XX_RBBM_INT_0_MASK_RBBM_ME_MS_TIMEOUT | \
395 A5XX_RBBM_INT_0_MASK_RBBM_PFP_MS_TIMEOUT | \
396 A5XX_RBBM_INT_0_MASK_RBBM_ETS_MS_TIMEOUT | \
397 A5XX_RBBM_INT_0_MASK_RBBM_ATB_ASYNC_OVERFLOW | \
398 A5XX_RBBM_INT_0_MASK_CP_HW_ERROR | \
Jordan Crouseac1b5ab2017-07-27 10:42:36 -0600399 A5XX_RBBM_INT_0_MASK_MISC_HANG_DETECT | \
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700400 A5XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS | \
401 A5XX_RBBM_INT_0_MASK_UCHE_OOB_ACCESS | \
402 A5XX_RBBM_INT_0_MASK_GPMU_VOLTAGE_DROOP)
403
404static int a5xx_hw_init(struct msm_gpu *gpu)
405{
406 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
407 int ret;
408
409 gpu_write(gpu, REG_A5XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x00000003);
410
411 /* Make all blocks contribute to the GPU BUSY perf counter */
412 gpu_write(gpu, REG_A5XX_RBBM_PERFCTR_GPU_BUSY_MASKED, 0xFFFFFFFF);
413
414 /* Enable RBBM error reporting bits */
415 gpu_write(gpu, REG_A5XX_RBBM_AHB_CNTL0, 0x00000001);
416
Rob Clark4e09b952017-01-30 11:15:14 -0500417 if (adreno_gpu->info->quirks & ADRENO_QUIRK_FAULT_DETECT_MASK) {
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700418 /*
419 * Mask out the activity signals from RB1-3 to avoid false
420 * positives
421 */
422
423 gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL11,
424 0xF0000000);
425 gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL12,
426 0xFFFFFFFF);
427 gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL13,
428 0xFFFFFFFF);
429 gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL14,
430 0xFFFFFFFF);
431 gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL15,
432 0xFFFFFFFF);
433 gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL16,
434 0xFFFFFFFF);
435 gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL17,
436 0xFFFFFFFF);
437 gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL18,
438 0xFFFFFFFF);
439 }
440
441 /* Enable fault detection */
442 gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_INT_CNTL,
443 (1 << 30) | 0xFFFF);
444
445 /* Turn on performance counters */
446 gpu_write(gpu, REG_A5XX_RBBM_PERFCTR_CNTL, 0x01);
447
448 /* Increase VFD cache access so LRZ and other data gets evicted less */
449 gpu_write(gpu, REG_A5XX_UCHE_CACHE_WAYS, 0x02);
450
451 /* Disable L2 bypass in the UCHE */
452 gpu_write(gpu, REG_A5XX_UCHE_TRAP_BASE_LO, 0xFFFF0000);
453 gpu_write(gpu, REG_A5XX_UCHE_TRAP_BASE_HI, 0x0001FFFF);
454 gpu_write(gpu, REG_A5XX_UCHE_WRITE_THRU_BASE_LO, 0xFFFF0000);
455 gpu_write(gpu, REG_A5XX_UCHE_WRITE_THRU_BASE_HI, 0x0001FFFF);
456
457 /* Set the GMEM VA range (0 to gpu->gmem) */
458 gpu_write(gpu, REG_A5XX_UCHE_GMEM_RANGE_MIN_LO, 0x00100000);
459 gpu_write(gpu, REG_A5XX_UCHE_GMEM_RANGE_MIN_HI, 0x00000000);
460 gpu_write(gpu, REG_A5XX_UCHE_GMEM_RANGE_MAX_LO,
461 0x00100000 + adreno_gpu->gmem - 1);
462 gpu_write(gpu, REG_A5XX_UCHE_GMEM_RANGE_MAX_HI, 0x00000000);
463
464 gpu_write(gpu, REG_A5XX_CP_MEQ_THRESHOLDS, 0x40);
465 gpu_write(gpu, REG_A5XX_CP_MERCIU_SIZE, 0x40);
466 gpu_write(gpu, REG_A5XX_CP_ROQ_THRESHOLDS_2, 0x80000060);
467 gpu_write(gpu, REG_A5XX_CP_ROQ_THRESHOLDS_1, 0x40201B16);
468
469 gpu_write(gpu, REG_A5XX_PC_DBG_ECO_CNTL, (0x400 << 11 | 0x300 << 22));
470
Rob Clark4e09b952017-01-30 11:15:14 -0500471 if (adreno_gpu->info->quirks & ADRENO_QUIRK_TWO_PASS_USE_WFI)
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700472 gpu_rmw(gpu, REG_A5XX_PC_DBG_ECO_CNTL, 0, (1 << 8));
473
474 gpu_write(gpu, REG_A5XX_PC_DBG_ECO_CNTL, 0xc0200100);
475
476 /* Enable USE_RETENTION_FLOPS */
477 gpu_write(gpu, REG_A5XX_CP_CHICKEN_DBG, 0x02000000);
478
479 /* Enable ME/PFP split notification */
480 gpu_write(gpu, REG_A5XX_RBBM_AHB_CNTL1, 0xA6FFFFFF);
481
482 /* Enable HWCG */
Jordan Crouse6e749e52017-07-27 10:42:31 -0600483 a5xx_set_hwcg(gpu, true);
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700484
485 gpu_write(gpu, REG_A5XX_RBBM_AHB_CNTL2, 0x0000003F);
486
487 /* Set the highest bank bit */
488 gpu_write(gpu, REG_A5XX_TPL1_MODE_CNTL, 2 << 7);
489 gpu_write(gpu, REG_A5XX_RB_MODE_CNTL, 2 << 1);
490
491 /* Protect registers from the CP */
492 gpu_write(gpu, REG_A5XX_CP_PROTECT_CNTL, 0x00000007);
493
494 /* RBBM */
495 gpu_write(gpu, REG_A5XX_CP_PROTECT(0), ADRENO_PROTECT_RW(0x04, 4));
496 gpu_write(gpu, REG_A5XX_CP_PROTECT(1), ADRENO_PROTECT_RW(0x08, 8));
497 gpu_write(gpu, REG_A5XX_CP_PROTECT(2), ADRENO_PROTECT_RW(0x10, 16));
498 gpu_write(gpu, REG_A5XX_CP_PROTECT(3), ADRENO_PROTECT_RW(0x20, 32));
499 gpu_write(gpu, REG_A5XX_CP_PROTECT(4), ADRENO_PROTECT_RW(0x40, 64));
500 gpu_write(gpu, REG_A5XX_CP_PROTECT(5), ADRENO_PROTECT_RW(0x80, 64));
501
502 /* Content protect */
503 gpu_write(gpu, REG_A5XX_CP_PROTECT(6),
504 ADRENO_PROTECT_RW(REG_A5XX_RBBM_SECVID_TSB_TRUSTED_BASE_LO,
505 16));
506 gpu_write(gpu, REG_A5XX_CP_PROTECT(7),
507 ADRENO_PROTECT_RW(REG_A5XX_RBBM_SECVID_TRUST_CNTL, 2));
508
509 /* CP */
510 gpu_write(gpu, REG_A5XX_CP_PROTECT(8), ADRENO_PROTECT_RW(0x800, 64));
511 gpu_write(gpu, REG_A5XX_CP_PROTECT(9), ADRENO_PROTECT_RW(0x840, 8));
512 gpu_write(gpu, REG_A5XX_CP_PROTECT(10), ADRENO_PROTECT_RW(0x880, 32));
513 gpu_write(gpu, REG_A5XX_CP_PROTECT(11), ADRENO_PROTECT_RW(0xAA0, 1));
514
515 /* RB */
516 gpu_write(gpu, REG_A5XX_CP_PROTECT(12), ADRENO_PROTECT_RW(0xCC0, 1));
517 gpu_write(gpu, REG_A5XX_CP_PROTECT(13), ADRENO_PROTECT_RW(0xCF0, 2));
518
519 /* VPC */
520 gpu_write(gpu, REG_A5XX_CP_PROTECT(14), ADRENO_PROTECT_RW(0xE68, 8));
521 gpu_write(gpu, REG_A5XX_CP_PROTECT(15), ADRENO_PROTECT_RW(0xE70, 4));
522
523 /* UCHE */
524 gpu_write(gpu, REG_A5XX_CP_PROTECT(16), ADRENO_PROTECT_RW(0xE80, 16));
525
526 if (adreno_is_a530(adreno_gpu))
527 gpu_write(gpu, REG_A5XX_CP_PROTECT(17),
528 ADRENO_PROTECT_RW(0x10000, 0x8000));
529
530 gpu_write(gpu, REG_A5XX_RBBM_SECVID_TSB_CNTL, 0);
531 /*
532 * Disable the trusted memory range - we don't actually supported secure
533 * memory rendering at this point in time and we don't want to block off
534 * part of the virtual memory space.
535 */
536 gpu_write64(gpu, REG_A5XX_RBBM_SECVID_TSB_TRUSTED_BASE_LO,
537 REG_A5XX_RBBM_SECVID_TSB_TRUSTED_BASE_HI, 0x00000000);
538 gpu_write(gpu, REG_A5XX_RBBM_SECVID_TSB_TRUSTED_SIZE, 0x00000000);
539
Jordan Crouse2401a002016-11-28 12:28:34 -0700540 /* Load the GPMU firmware before starting the HW init */
541 a5xx_gpmu_ucode_init(gpu);
542
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700543 ret = adreno_hw_init(gpu);
544 if (ret)
545 return ret;
546
547 ret = a5xx_ucode_init(gpu);
548 if (ret)
549 return ret;
550
551 /* Disable the interrupts through the initial bringup stage */
552 gpu_write(gpu, REG_A5XX_RBBM_INT_0_MASK, A5XX_INT_MASK);
553
554 /* Clear ME_HALT to start the micro engine */
555 gpu_write(gpu, REG_A5XX_CP_PFP_ME_CNTL, 0);
556 ret = a5xx_me_init(gpu);
557 if (ret)
558 return ret;
559
Jordan Crouse2401a002016-11-28 12:28:34 -0700560 ret = a5xx_power_init(gpu);
561 if (ret)
562 return ret;
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700563
564 /*
565 * Send a pipeline event stat to get misbehaving counters to start
566 * ticking correctly
567 */
568 if (adreno_is_a530(adreno_gpu)) {
569 OUT_PKT7(gpu->rb, CP_EVENT_WRITE, 1);
570 OUT_RING(gpu->rb, 0x0F);
571
572 gpu->funcs->flush(gpu);
Jordan Crousee895c7b2017-05-08 14:35:00 -0600573 if (!a5xx_idle(gpu))
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700574 return -EINVAL;
575 }
576
Jordan Crouse7c658172017-05-17 08:45:29 -0600577 /*
578 * Try to load a zap shader into the secure world. If successful
579 * we can use the CP to switch out of secure mode. If not then we
580 * have no resource but to try to switch ourselves out manually. If we
581 * guessed wrong then access to the RBBM_SECVID_TRUST_CNTL register will
582 * be blocked and a permissions violation will soon follow.
583 */
584 ret = a5xx_zap_shader_init(gpu);
585 if (!ret) {
586 OUT_PKT7(gpu->rb, CP_SET_SECURE_MODE, 1);
587 OUT_RING(gpu->rb, 0x00000000);
588
589 gpu->funcs->flush(gpu);
Jordan Crousee895c7b2017-05-08 14:35:00 -0600590 if (!a5xx_idle(gpu))
Jordan Crouse7c658172017-05-17 08:45:29 -0600591 return -EINVAL;
592 } else {
593 /* Print a warning so if we die, we know why */
594 dev_warn_once(gpu->dev->dev,
595 "Zap shader not enabled - using SECVID_TRUST_CNTL instead\n");
596 gpu_write(gpu, REG_A5XX_RBBM_SECVID_TRUST_CNTL, 0x0);
597 }
Jordan Crouse2401a002016-11-28 12:28:34 -0700598
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700599 return 0;
600}
601
602static void a5xx_recover(struct msm_gpu *gpu)
603{
604 int i;
605
606 adreno_dump_info(gpu);
607
608 for (i = 0; i < 8; i++) {
609 printk("CP_SCRATCH_REG%d: %u\n", i,
610 gpu_read(gpu, REG_A5XX_CP_SCRATCH_REG(i)));
611 }
612
613 if (hang_debug)
614 a5xx_dump(gpu);
615
616 gpu_write(gpu, REG_A5XX_RBBM_SW_RESET_CMD, 1);
617 gpu_read(gpu, REG_A5XX_RBBM_SW_RESET_CMD);
618 gpu_write(gpu, REG_A5XX_RBBM_SW_RESET_CMD, 0);
619 adreno_recover(gpu);
620}
621
622static void a5xx_destroy(struct msm_gpu *gpu)
623{
624 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
625 struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu);
626
627 DBG("%s", gpu->name);
628
629 if (a5xx_gpu->pm4_bo) {
630 if (a5xx_gpu->pm4_iova)
Rob Clark8bdcd942017-06-13 11:07:08 -0400631 msm_gem_put_iova(a5xx_gpu->pm4_bo, gpu->aspace);
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700632 drm_gem_object_unreference_unlocked(a5xx_gpu->pm4_bo);
633 }
634
635 if (a5xx_gpu->pfp_bo) {
636 if (a5xx_gpu->pfp_iova)
Rob Clark8bdcd942017-06-13 11:07:08 -0400637 msm_gem_put_iova(a5xx_gpu->pfp_bo, gpu->aspace);
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700638 drm_gem_object_unreference_unlocked(a5xx_gpu->pfp_bo);
639 }
640
Jordan Crouse2401a002016-11-28 12:28:34 -0700641 if (a5xx_gpu->gpmu_bo) {
Jordan Crouse2002c9c2017-03-07 09:50:27 -0700642 if (a5xx_gpu->gpmu_iova)
Rob Clark8bdcd942017-06-13 11:07:08 -0400643 msm_gem_put_iova(a5xx_gpu->gpmu_bo, gpu->aspace);
Jordan Crouse2401a002016-11-28 12:28:34 -0700644 drm_gem_object_unreference_unlocked(a5xx_gpu->gpmu_bo);
645 }
646
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700647 adreno_gpu_cleanup(adreno_gpu);
648 kfree(a5xx_gpu);
649}
650
651static inline bool _a5xx_check_idle(struct msm_gpu *gpu)
652{
653 if (gpu_read(gpu, REG_A5XX_RBBM_STATUS) & ~A5XX_RBBM_STATUS_HI_BUSY)
654 return false;
655
656 /*
657 * Nearly every abnormality ends up pausing the GPU and triggering a
658 * fault so we can safely just watch for this one interrupt to fire
659 */
660 return !(gpu_read(gpu, REG_A5XX_RBBM_INT_0_STATUS) &
661 A5XX_RBBM_INT_0_MASK_MISC_HANG_DETECT);
662}
663
Jordan Crousee895c7b2017-05-08 14:35:00 -0600664bool a5xx_idle(struct msm_gpu *gpu)
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700665{
666 /* wait for CP to drain ringbuffer: */
667 if (!adreno_idle(gpu))
668 return false;
669
670 if (spin_until(_a5xx_check_idle(gpu))) {
671 DRM_ERROR("%s: %ps: timeout waiting for GPU to idle: status %8.8X irq %8.8X\n",
672 gpu->name, __builtin_return_address(0),
673 gpu_read(gpu, REG_A5XX_RBBM_STATUS),
674 gpu_read(gpu, REG_A5XX_RBBM_INT_0_STATUS));
675
676 return false;
677 }
678
679 return true;
680}
681
Rob Clark7f8036b2016-12-07 11:13:53 -0500682static int a5xx_fault_handler(void *arg, unsigned long iova, int flags)
683{
684 struct msm_gpu *gpu = arg;
685 pr_warn_ratelimited("*** gpu fault: iova=%08lx, flags=%d (%u,%u,%u,%u)\n",
686 iova, flags,
687 gpu_read(gpu, REG_A5XX_CP_SCRATCH_REG(4)),
688 gpu_read(gpu, REG_A5XX_CP_SCRATCH_REG(5)),
689 gpu_read(gpu, REG_A5XX_CP_SCRATCH_REG(6)),
690 gpu_read(gpu, REG_A5XX_CP_SCRATCH_REG(7)));
691
692 return -EFAULT;
693}
694
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700695static void a5xx_cp_err_irq(struct msm_gpu *gpu)
696{
697 u32 status = gpu_read(gpu, REG_A5XX_CP_INTERRUPT_STATUS);
698
699 if (status & A5XX_CP_INT_CP_OPCODE_ERROR) {
700 u32 val;
701
702 gpu_write(gpu, REG_A5XX_CP_PFP_STAT_ADDR, 0);
703
704 /*
705 * REG_A5XX_CP_PFP_STAT_DATA is indexed, and we want index 1 so
706 * read it twice
707 */
708
709 gpu_read(gpu, REG_A5XX_CP_PFP_STAT_DATA);
710 val = gpu_read(gpu, REG_A5XX_CP_PFP_STAT_DATA);
711
712 dev_err_ratelimited(gpu->dev->dev, "CP | opcode error | possible opcode=0x%8.8X\n",
713 val);
714 }
715
716 if (status & A5XX_CP_INT_CP_HW_FAULT_ERROR)
717 dev_err_ratelimited(gpu->dev->dev, "CP | HW fault | status=0x%8.8X\n",
718 gpu_read(gpu, REG_A5XX_CP_HW_FAULT));
719
720 if (status & A5XX_CP_INT_CP_DMA_ERROR)
721 dev_err_ratelimited(gpu->dev->dev, "CP | DMA error\n");
722
723 if (status & A5XX_CP_INT_CP_REGISTER_PROTECTION_ERROR) {
724 u32 val = gpu_read(gpu, REG_A5XX_CP_PROTECT_STATUS);
725
726 dev_err_ratelimited(gpu->dev->dev,
727 "CP | protected mode error | %s | addr=0x%8.8X | status=0x%8.8X\n",
728 val & (1 << 24) ? "WRITE" : "READ",
729 (val & 0xFFFFF) >> 2, val);
730 }
731
732 if (status & A5XX_CP_INT_CP_AHB_ERROR) {
733 u32 status = gpu_read(gpu, REG_A5XX_CP_AHB_FAULT);
734 const char *access[16] = { "reserved", "reserved",
735 "timestamp lo", "timestamp hi", "pfp read", "pfp write",
736 "", "", "me read", "me write", "", "", "crashdump read",
737 "crashdump write" };
738
739 dev_err_ratelimited(gpu->dev->dev,
740 "CP | AHB error | addr=%X access=%s error=%d | status=0x%8.8X\n",
741 status & 0xFFFFF, access[(status >> 24) & 0xF],
742 (status & (1 << 31)), status);
743 }
744}
745
Jordan Crouse7352fb52017-03-07 09:50:29 -0700746static void a5xx_rbbm_err_irq(struct msm_gpu *gpu, u32 status)
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700747{
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700748 if (status & A5XX_RBBM_INT_0_MASK_RBBM_AHB_ERROR) {
749 u32 val = gpu_read(gpu, REG_A5XX_RBBM_AHB_ERROR_STATUS);
750
751 dev_err_ratelimited(gpu->dev->dev,
752 "RBBM | AHB bus error | %s | addr=0x%X | ports=0x%X:0x%X\n",
753 val & (1 << 28) ? "WRITE" : "READ",
754 (val & 0xFFFFF) >> 2, (val >> 20) & 0x3,
755 (val >> 24) & 0xF);
756
757 /* Clear the error */
758 gpu_write(gpu, REG_A5XX_RBBM_AHB_CMD, (1 << 4));
Jordan Crouse7352fb52017-03-07 09:50:29 -0700759
760 /* Clear the interrupt */
761 gpu_write(gpu, REG_A5XX_RBBM_INT_CLEAR_CMD,
762 A5XX_RBBM_INT_0_MASK_RBBM_AHB_ERROR);
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700763 }
764
765 if (status & A5XX_RBBM_INT_0_MASK_RBBM_TRANSFER_TIMEOUT)
766 dev_err_ratelimited(gpu->dev->dev, "RBBM | AHB transfer timeout\n");
767
768 if (status & A5XX_RBBM_INT_0_MASK_RBBM_ME_MS_TIMEOUT)
769 dev_err_ratelimited(gpu->dev->dev, "RBBM | ME master split | status=0x%X\n",
770 gpu_read(gpu, REG_A5XX_RBBM_AHB_ME_SPLIT_STATUS));
771
772 if (status & A5XX_RBBM_INT_0_MASK_RBBM_PFP_MS_TIMEOUT)
773 dev_err_ratelimited(gpu->dev->dev, "RBBM | PFP master split | status=0x%X\n",
774 gpu_read(gpu, REG_A5XX_RBBM_AHB_PFP_SPLIT_STATUS));
775
776 if (status & A5XX_RBBM_INT_0_MASK_RBBM_ETS_MS_TIMEOUT)
777 dev_err_ratelimited(gpu->dev->dev, "RBBM | ETS master split | status=0x%X\n",
778 gpu_read(gpu, REG_A5XX_RBBM_AHB_ETS_SPLIT_STATUS));
779
780 if (status & A5XX_RBBM_INT_0_MASK_RBBM_ATB_ASYNC_OVERFLOW)
781 dev_err_ratelimited(gpu->dev->dev, "RBBM | ATB ASYNC overflow\n");
782
783 if (status & A5XX_RBBM_INT_0_MASK_RBBM_ATB_BUS_OVERFLOW)
784 dev_err_ratelimited(gpu->dev->dev, "RBBM | ATB bus overflow\n");
785}
786
787static void a5xx_uche_err_irq(struct msm_gpu *gpu)
788{
789 uint64_t addr = (uint64_t) gpu_read(gpu, REG_A5XX_UCHE_TRAP_LOG_HI);
790
791 addr |= gpu_read(gpu, REG_A5XX_UCHE_TRAP_LOG_LO);
792
793 dev_err_ratelimited(gpu->dev->dev, "UCHE | Out of bounds access | addr=0x%llX\n",
794 addr);
795}
796
797static void a5xx_gpmu_err_irq(struct msm_gpu *gpu)
798{
799 dev_err_ratelimited(gpu->dev->dev, "GPMU | voltage droop\n");
800}
801
Jordan Crouseac1b5ab2017-07-27 10:42:36 -0600802static void a5xx_fault_detect_irq(struct msm_gpu *gpu)
803{
804 struct drm_device *dev = gpu->dev;
805 struct msm_drm_private *priv = dev->dev_private;
Jordan Crouseac1b5ab2017-07-27 10:42:36 -0600806
Jordan Crouse1267a4d2017-07-27 10:42:39 -0600807 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",
808 gpu->funcs->last_fence(gpu),
Jordan Crouseac1b5ab2017-07-27 10:42:36 -0600809 gpu_read(gpu, REG_A5XX_RBBM_STATUS),
810 gpu_read(gpu, REG_A5XX_CP_RB_RPTR),
811 gpu_read(gpu, REG_A5XX_CP_RB_WPTR),
812 gpu_read64(gpu, REG_A5XX_CP_IB1_BASE, REG_A5XX_CP_IB1_BASE_HI),
813 gpu_read(gpu, REG_A5XX_CP_IB1_BUFSZ),
814 gpu_read64(gpu, REG_A5XX_CP_IB2_BASE, REG_A5XX_CP_IB2_BASE_HI),
815 gpu_read(gpu, REG_A5XX_CP_IB2_BUFSZ));
816
817 /* Turn off the hangcheck timer to keep it from bothering us */
818 del_timer(&gpu->hangcheck_timer);
819
820 queue_work(priv->wq, &gpu->recover_work);
821}
822
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700823#define RBBM_ERROR_MASK \
824 (A5XX_RBBM_INT_0_MASK_RBBM_AHB_ERROR | \
825 A5XX_RBBM_INT_0_MASK_RBBM_TRANSFER_TIMEOUT | \
826 A5XX_RBBM_INT_0_MASK_RBBM_ME_MS_TIMEOUT | \
827 A5XX_RBBM_INT_0_MASK_RBBM_PFP_MS_TIMEOUT | \
828 A5XX_RBBM_INT_0_MASK_RBBM_ETS_MS_TIMEOUT | \
829 A5XX_RBBM_INT_0_MASK_RBBM_ATB_ASYNC_OVERFLOW)
830
831static irqreturn_t a5xx_irq(struct msm_gpu *gpu)
832{
833 u32 status = gpu_read(gpu, REG_A5XX_RBBM_INT_0_STATUS);
834
Jordan Crouse7352fb52017-03-07 09:50:29 -0700835 /*
836 * Clear all the interrupts except RBBM_AHB_ERROR - if we clear it
837 * before the source is cleared the interrupt will storm.
838 */
839 gpu_write(gpu, REG_A5XX_RBBM_INT_CLEAR_CMD,
840 status & ~A5XX_RBBM_INT_0_MASK_RBBM_AHB_ERROR);
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700841
Jordan Crouse7352fb52017-03-07 09:50:29 -0700842 /* Pass status to a5xx_rbbm_err_irq because we've already cleared it */
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700843 if (status & RBBM_ERROR_MASK)
Jordan Crouse7352fb52017-03-07 09:50:29 -0700844 a5xx_rbbm_err_irq(gpu, status);
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700845
846 if (status & A5XX_RBBM_INT_0_MASK_CP_HW_ERROR)
847 a5xx_cp_err_irq(gpu);
848
Jordan Crouseac1b5ab2017-07-27 10:42:36 -0600849 if (status & A5XX_RBBM_INT_0_MASK_MISC_HANG_DETECT)
850 a5xx_fault_detect_irq(gpu);
851
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700852 if (status & A5XX_RBBM_INT_0_MASK_UCHE_OOB_ACCESS)
853 a5xx_uche_err_irq(gpu);
854
855 if (status & A5XX_RBBM_INT_0_MASK_GPMU_VOLTAGE_DROOP)
856 a5xx_gpmu_err_irq(gpu);
857
858 if (status & A5XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS)
859 msm_gpu_retire(gpu);
860
861 return IRQ_HANDLED;
862}
863
864static const u32 a5xx_register_offsets[REG_ADRENO_REGISTER_MAX] = {
865 REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_BASE, REG_A5XX_CP_RB_BASE),
866 REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_BASE_HI, REG_A5XX_CP_RB_BASE_HI),
867 REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_RPTR_ADDR, REG_A5XX_CP_RB_RPTR_ADDR),
868 REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_RPTR_ADDR_HI,
869 REG_A5XX_CP_RB_RPTR_ADDR_HI),
870 REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_RPTR, REG_A5XX_CP_RB_RPTR),
871 REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_WPTR, REG_A5XX_CP_RB_WPTR),
872 REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_CNTL, REG_A5XX_CP_RB_CNTL),
873};
874
875static const u32 a5xx_registers[] = {
876 0x0000, 0x0002, 0x0004, 0x0020, 0x0022, 0x0026, 0x0029, 0x002B,
877 0x002E, 0x0035, 0x0038, 0x0042, 0x0044, 0x0044, 0x0047, 0x0095,
878 0x0097, 0x00BB, 0x03A0, 0x0464, 0x0469, 0x046F, 0x04D2, 0x04D3,
Jordan Crouse3394f562017-07-27 10:42:30 -0600879 0x04E0, 0x0533, 0x0540, 0x0555, 0x0800, 0x081A, 0x081F, 0x0841,
880 0x0860, 0x0860, 0x0880, 0x08A0, 0x0B00, 0x0B12, 0x0B15, 0x0B28,
881 0x0B78, 0x0B7F, 0x0BB0, 0x0BBD, 0x0BC0, 0x0BC6, 0x0BD0, 0x0C53,
882 0x0C60, 0x0C61, 0x0C80, 0x0C82, 0x0C84, 0x0C85, 0x0C90, 0x0C98,
883 0x0CA0, 0x0CA0, 0x0CB0, 0x0CB2, 0x2180, 0x2185, 0x2580, 0x2585,
884 0x0CC1, 0x0CC1, 0x0CC4, 0x0CC7, 0x0CCC, 0x0CCC, 0x0CD0, 0x0CD8,
885 0x0CE0, 0x0CE5, 0x0CE8, 0x0CE8, 0x0CEC, 0x0CF1, 0x0CFB, 0x0D0E,
886 0x2100, 0x211E, 0x2140, 0x2145, 0x2500, 0x251E, 0x2540, 0x2545,
887 0x0D10, 0x0D17, 0x0D20, 0x0D23, 0x0D30, 0x0D30, 0x20C0, 0x20C0,
888 0x24C0, 0x24C0, 0x0E40, 0x0E43, 0x0E4A, 0x0E4A, 0x0E50, 0x0E57,
889 0x0E60, 0x0E7C, 0x0E80, 0x0E8E, 0x0E90, 0x0E96, 0x0EA0, 0x0EA8,
890 0x0EB0, 0x0EB2, 0xE140, 0xE147, 0xE150, 0xE187, 0xE1A0, 0xE1A9,
891 0xE1B0, 0xE1B6, 0xE1C0, 0xE1C7, 0xE1D0, 0xE1D1, 0xE200, 0xE201,
892 0xE210, 0xE21C, 0xE240, 0xE268, 0xE000, 0xE006, 0xE010, 0xE09A,
893 0xE0A0, 0xE0A4, 0xE0AA, 0xE0EB, 0xE100, 0xE105, 0xE380, 0xE38F,
894 0xE3B0, 0xE3B0, 0xE400, 0xE405, 0xE408, 0xE4E9, 0xE4F0, 0xE4F0,
895 0xE280, 0xE280, 0xE282, 0xE2A3, 0xE2A5, 0xE2C2, 0xE940, 0xE947,
896 0xE950, 0xE987, 0xE9A0, 0xE9A9, 0xE9B0, 0xE9B6, 0xE9C0, 0xE9C7,
897 0xE9D0, 0xE9D1, 0xEA00, 0xEA01, 0xEA10, 0xEA1C, 0xEA40, 0xEA68,
898 0xE800, 0xE806, 0xE810, 0xE89A, 0xE8A0, 0xE8A4, 0xE8AA, 0xE8EB,
899 0xE900, 0xE905, 0xEB80, 0xEB8F, 0xEBB0, 0xEBB0, 0xEC00, 0xEC05,
900 0xEC08, 0xECE9, 0xECF0, 0xECF0, 0xEA80, 0xEA80, 0xEA82, 0xEAA3,
901 0xEAA5, 0xEAC2, 0xA800, 0xA8FF, 0xAC60, 0xAC60, 0xB000, 0xB97F,
902 0xB9A0, 0xB9BF, ~0
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700903};
904
905static void a5xx_dump(struct msm_gpu *gpu)
906{
907 dev_info(gpu->dev->dev, "status: %08x\n",
908 gpu_read(gpu, REG_A5XX_RBBM_STATUS));
909 adreno_dump(gpu);
910}
911
912static int a5xx_pm_resume(struct msm_gpu *gpu)
913{
Jordan Crouse2401a002016-11-28 12:28:34 -0700914 int ret;
915
916 /* Turn on the core power */
917 ret = msm_gpu_pm_resume(gpu);
918 if (ret)
919 return ret;
920
921 /* Turn the RBCCU domain first to limit the chances of voltage droop */
922 gpu_write(gpu, REG_A5XX_GPMU_RBCCU_POWER_CNTL, 0x778000);
923
924 /* Wait 3 usecs before polling */
925 udelay(3);
926
927 ret = spin_usecs(gpu, 20, REG_A5XX_GPMU_RBCCU_PWR_CLK_STATUS,
928 (1 << 20), (1 << 20));
929 if (ret) {
930 DRM_ERROR("%s: timeout waiting for RBCCU GDSC enable: %X\n",
931 gpu->name,
932 gpu_read(gpu, REG_A5XX_GPMU_RBCCU_PWR_CLK_STATUS));
933 return ret;
934 }
935
936 /* Turn on the SP domain */
937 gpu_write(gpu, REG_A5XX_GPMU_SP_POWER_CNTL, 0x778000);
938 ret = spin_usecs(gpu, 20, REG_A5XX_GPMU_SP_PWR_CLK_STATUS,
939 (1 << 20), (1 << 20));
940 if (ret)
941 DRM_ERROR("%s: timeout waiting for SP GDSC enable\n",
942 gpu->name);
943
944 return ret;
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700945}
946
947static int a5xx_pm_suspend(struct msm_gpu *gpu)
948{
Jordan Crouse2401a002016-11-28 12:28:34 -0700949 /* Clear the VBIF pipe before shutting down */
950 gpu_write(gpu, REG_A5XX_VBIF_XIN_HALT_CTRL0, 0xF);
951 spin_until((gpu_read(gpu, REG_A5XX_VBIF_XIN_HALT_CTRL1) & 0xF) == 0xF);
952
953 gpu_write(gpu, REG_A5XX_VBIF_XIN_HALT_CTRL0, 0);
954
955 /*
956 * Reset the VBIF before power collapse to avoid issue with FIFO
957 * entries
958 */
959 gpu_write(gpu, REG_A5XX_RBBM_BLOCK_SW_RESET_CMD, 0x003C0000);
960 gpu_write(gpu, REG_A5XX_RBBM_BLOCK_SW_RESET_CMD, 0x00000000);
961
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700962 return msm_gpu_pm_suspend(gpu);
963}
964
965static int a5xx_get_timestamp(struct msm_gpu *gpu, uint64_t *value)
966{
967 *value = gpu_read64(gpu, REG_A5XX_RBBM_PERFCTR_CP_0_LO,
968 REG_A5XX_RBBM_PERFCTR_CP_0_HI);
969
970 return 0;
971}
972
973#ifdef CONFIG_DEBUG_FS
974static void a5xx_show(struct msm_gpu *gpu, struct seq_file *m)
975{
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700976 seq_printf(m, "status: %08x\n",
977 gpu_read(gpu, REG_A5XX_RBBM_STATUS));
Jordan Crousea23cb3b2017-07-27 10:42:32 -0600978
979 /*
980 * Temporarily disable hardware clock gating before going into
981 * adreno_show to avoid issues while reading the registers
982 */
983 a5xx_set_hwcg(gpu, false);
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700984 adreno_show(gpu, m);
Jordan Crousea23cb3b2017-07-27 10:42:32 -0600985 a5xx_set_hwcg(gpu, true);
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700986}
987#endif
988
989static const struct adreno_gpu_funcs funcs = {
990 .base = {
991 .get_param = adreno_get_param,
992 .hw_init = a5xx_hw_init,
993 .pm_suspend = a5xx_pm_suspend,
994 .pm_resume = a5xx_pm_resume,
995 .recover = a5xx_recover,
996 .last_fence = adreno_last_fence,
997 .submit = a5xx_submit,
998 .flush = adreno_flush,
Jordan Crouseb5f103a2016-11-28 12:28:33 -0700999 .irq = a5xx_irq,
1000 .destroy = a5xx_destroy,
Arnd Bergmann0c3eaf12017-03-13 17:43:48 +01001001#ifdef CONFIG_DEBUG_FS
Jordan Crouseb5f103a2016-11-28 12:28:33 -07001002 .show = a5xx_show,
Arnd Bergmann0c3eaf12017-03-13 17:43:48 +01001003#endif
Jordan Crouseb5f103a2016-11-28 12:28:33 -07001004 },
1005 .get_timestamp = a5xx_get_timestamp,
1006};
1007
1008struct msm_gpu *a5xx_gpu_init(struct drm_device *dev)
1009{
1010 struct msm_drm_private *priv = dev->dev_private;
1011 struct platform_device *pdev = priv->gpu_pdev;
1012 struct a5xx_gpu *a5xx_gpu = NULL;
1013 struct adreno_gpu *adreno_gpu;
1014 struct msm_gpu *gpu;
1015 int ret;
1016
1017 if (!pdev) {
1018 dev_err(dev->dev, "No A5XX device is defined\n");
1019 return ERR_PTR(-ENXIO);
1020 }
1021
1022 a5xx_gpu = kzalloc(sizeof(*a5xx_gpu), GFP_KERNEL);
1023 if (!a5xx_gpu)
1024 return ERR_PTR(-ENOMEM);
1025
1026 adreno_gpu = &a5xx_gpu->base;
1027 gpu = &adreno_gpu->base;
1028
Jordan Crouseb5f103a2016-11-28 12:28:33 -07001029 adreno_gpu->registers = a5xx_registers;
1030 adreno_gpu->reg_offsets = a5xx_register_offsets;
1031
Jordan Crouse2401a002016-11-28 12:28:34 -07001032 a5xx_gpu->lm_leakage = 0x4E001A;
1033
Jordan Crouseb5f103a2016-11-28 12:28:33 -07001034 ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs);
1035 if (ret) {
1036 a5xx_destroy(&(a5xx_gpu->base.base));
1037 return ERR_PTR(ret);
1038 }
1039
Rob Clark7f8036b2016-12-07 11:13:53 -05001040 if (gpu->aspace)
1041 msm_mmu_set_fault_handler(gpu->aspace->mmu, gpu, a5xx_fault_handler);
1042
Jordan Crouseb5f103a2016-11-28 12:28:33 -07001043 return gpu;
1044}