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