blob: 8199a4b9f2faf5efaa33fd2cd84fa011eb3401bd [file] [log] [blame]
Aravind Ganesan23bd62f2014-09-08 13:40:16 -06001/* Copyright (c) 2014 The Linux Foundation. All rights reserved.
2 *
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#include "a4xx_gpu.h"
14#ifdef CONFIG_MSM_OCMEM
15# include <soc/qcom/ocmem.h>
16#endif
17
18#define A4XX_INT0_MASK \
19 (A4XX_INT0_RBBM_AHB_ERROR | \
20 A4XX_INT0_RBBM_ATB_BUS_OVERFLOW | \
21 A4XX_INT0_CP_T0_PACKET_IN_IB | \
22 A4XX_INT0_CP_OPCODE_ERROR | \
23 A4XX_INT0_CP_RESERVED_BIT_ERROR | \
24 A4XX_INT0_CP_HW_FAULT | \
25 A4XX_INT0_CP_IB1_INT | \
26 A4XX_INT0_CP_IB2_INT | \
27 A4XX_INT0_CP_RB_INT | \
28 A4XX_INT0_CP_REG_PROTECT_FAULT | \
29 A4XX_INT0_CP_AHB_ERROR_HALT | \
30 A4XX_INT0_UCHE_OOB_ACCESS)
31
32extern bool hang_debug;
33static void a4xx_dump(struct msm_gpu *gpu);
Jordan Crousee895c7b2017-05-08 14:35:00 -060034static bool a4xx_idle(struct msm_gpu *gpu);
Aravind Ganesan23bd62f2014-09-08 13:40:16 -060035
36/*
37 * a4xx_enable_hwcg() - Program the clock control registers
38 * @device: The adreno device pointer
39 */
40static void a4xx_enable_hwcg(struct msm_gpu *gpu)
41{
42 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
43 unsigned int i;
44 for (i = 0; i < 4; i++)
45 gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL_TP(i), 0x02222202);
46 for (i = 0; i < 4; i++)
47 gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL2_TP(i), 0x00002222);
48 for (i = 0; i < 4; i++)
49 gpu_write(gpu, REG_A4XX_RBBM_CLOCK_HYST_TP(i), 0x0E739CE7);
50 for (i = 0; i < 4; i++)
51 gpu_write(gpu, REG_A4XX_RBBM_CLOCK_DELAY_TP(i), 0x00111111);
52 for (i = 0; i < 4; i++)
53 gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL_SP(i), 0x22222222);
54 for (i = 0; i < 4; i++)
55 gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL2_SP(i), 0x00222222);
56 for (i = 0; i < 4; i++)
57 gpu_write(gpu, REG_A4XX_RBBM_CLOCK_HYST_SP(i), 0x00000104);
58 for (i = 0; i < 4; i++)
59 gpu_write(gpu, REG_A4XX_RBBM_CLOCK_DELAY_SP(i), 0x00000081);
60 gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL_UCHE, 0x22222222);
61 gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL2_UCHE, 0x02222222);
62 gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL3_UCHE, 0x00000000);
63 gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL4_UCHE, 0x00000000);
64 gpu_write(gpu, REG_A4XX_RBBM_CLOCK_HYST_UCHE, 0x00004444);
65 gpu_write(gpu, REG_A4XX_RBBM_CLOCK_DELAY_UCHE, 0x00001112);
66 for (i = 0; i < 4; i++)
67 gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL_RB(i), 0x22222222);
68
69 /* Disable L1 clocking in A420 due to CCU issues with it */
70 for (i = 0; i < 4; i++) {
71 if (adreno_is_a420(adreno_gpu)) {
72 gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL2_RB(i),
73 0x00002020);
74 } else {
75 gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL2_RB(i),
76 0x00022020);
77 }
78 }
79
80 for (i = 0; i < 4; i++) {
81 gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL_MARB_CCU(i),
82 0x00000922);
83 }
84
85 for (i = 0; i < 4; i++) {
86 gpu_write(gpu, REG_A4XX_RBBM_CLOCK_HYST_RB_MARB_CCU(i),
87 0x00000000);
88 }
89
90 for (i = 0; i < 4; i++) {
91 gpu_write(gpu, REG_A4XX_RBBM_CLOCK_DELAY_RB_MARB_CCU_L1(i),
92 0x00000001);
93 }
94
95 gpu_write(gpu, REG_A4XX_RBBM_CLOCK_MODE_GPC, 0x02222222);
96 gpu_write(gpu, REG_A4XX_RBBM_CLOCK_HYST_GPC, 0x04100104);
97 gpu_write(gpu, REG_A4XX_RBBM_CLOCK_DELAY_GPC, 0x00022222);
98 gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL_COM_DCOM, 0x00000022);
99 gpu_write(gpu, REG_A4XX_RBBM_CLOCK_HYST_COM_DCOM, 0x0000010F);
100 gpu_write(gpu, REG_A4XX_RBBM_CLOCK_DELAY_COM_DCOM, 0x00000022);
101 gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL_TSE_RAS_RBBM, 0x00222222);
102 gpu_write(gpu, REG_A4XX_RBBM_CLOCK_HYST_TSE_RAS_RBBM, 0x00004104);
103 gpu_write(gpu, REG_A4XX_RBBM_CLOCK_DELAY_TSE_RAS_RBBM, 0x00000222);
104 gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL_HLSQ , 0x00000000);
105 gpu_write(gpu, REG_A4XX_RBBM_CLOCK_HYST_HLSQ, 0x00000000);
Craig Stout357ff002016-02-18 16:50:00 -0800106 gpu_write(gpu, REG_A4XX_RBBM_CLOCK_DELAY_HLSQ, 0x00220000);
107 /* Early A430's have a timing issue with SP/TP power collapse;
108 disabling HW clock gating prevents it. */
109 if (adreno_is_a430(adreno_gpu) && adreno_gpu->rev.patchid < 2)
110 gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL, 0);
111 else
112 gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL, 0xAAAAAAAA);
Aravind Ganesan23bd62f2014-09-08 13:40:16 -0600113 gpu_write(gpu, REG_A4XX_RBBM_CLOCK_CTL2, 0);
114}
115
Craig Stout357ff002016-02-18 16:50:00 -0800116
Jordan Crousec4a8d4752016-11-28 12:28:27 -0700117static bool a4xx_me_init(struct msm_gpu *gpu)
Aravind Ganesan23bd62f2014-09-08 13:40:16 -0600118{
Jordan Crousef97deca2017-10-20 11:06:57 -0600119 struct msm_ringbuffer *ring = gpu->rb[0];
Aravind Ganesan23bd62f2014-09-08 13:40:16 -0600120
121 OUT_PKT3(ring, CP_ME_INIT, 17);
122 OUT_RING(ring, 0x000003f7);
123 OUT_RING(ring, 0x00000000);
124 OUT_RING(ring, 0x00000000);
125 OUT_RING(ring, 0x00000000);
126 OUT_RING(ring, 0x00000080);
127 OUT_RING(ring, 0x00000100);
128 OUT_RING(ring, 0x00000180);
129 OUT_RING(ring, 0x00006600);
130 OUT_RING(ring, 0x00000150);
131 OUT_RING(ring, 0x0000014e);
132 OUT_RING(ring, 0x00000154);
133 OUT_RING(ring, 0x00000001);
134 OUT_RING(ring, 0x00000000);
135 OUT_RING(ring, 0x00000000);
136 OUT_RING(ring, 0x00000000);
137 OUT_RING(ring, 0x00000000);
138 OUT_RING(ring, 0x00000000);
139
Jordan Crousef97deca2017-10-20 11:06:57 -0600140 gpu->funcs->flush(gpu, ring);
Jordan Crousee895c7b2017-05-08 14:35:00 -0600141 return a4xx_idle(gpu);
Aravind Ganesan23bd62f2014-09-08 13:40:16 -0600142}
143
144static int a4xx_hw_init(struct msm_gpu *gpu)
145{
146 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
147 struct a4xx_gpu *a4xx_gpu = to_a4xx_gpu(adreno_gpu);
148 uint32_t *ptr, len;
149 int i, ret;
150
Craig Stout357ff002016-02-18 16:50:00 -0800151 if (adreno_is_a420(adreno_gpu)) {
Aravind Ganesan23bd62f2014-09-08 13:40:16 -0600152 gpu_write(gpu, REG_A4XX_VBIF_ABIT_SORT, 0x0001001F);
153 gpu_write(gpu, REG_A4XX_VBIF_ABIT_SORT_CONF, 0x000000A4);
154 gpu_write(gpu, REG_A4XX_VBIF_GATE_OFF_WRREQ_EN, 0x00000001);
155 gpu_write(gpu, REG_A4XX_VBIF_IN_RD_LIM_CONF0, 0x18181818);
156 gpu_write(gpu, REG_A4XX_VBIF_IN_RD_LIM_CONF1, 0x00000018);
157 gpu_write(gpu, REG_A4XX_VBIF_IN_WR_LIM_CONF0, 0x18181818);
158 gpu_write(gpu, REG_A4XX_VBIF_IN_WR_LIM_CONF1, 0x00000018);
159 gpu_write(gpu, REG_A4XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x00000003);
Craig Stout357ff002016-02-18 16:50:00 -0800160 } else if (adreno_is_a430(adreno_gpu)) {
161 gpu_write(gpu, REG_A4XX_VBIF_GATE_OFF_WRREQ_EN, 0x00000001);
162 gpu_write(gpu, REG_A4XX_VBIF_IN_RD_LIM_CONF0, 0x18181818);
163 gpu_write(gpu, REG_A4XX_VBIF_IN_RD_LIM_CONF1, 0x00000018);
164 gpu_write(gpu, REG_A4XX_VBIF_IN_WR_LIM_CONF0, 0x18181818);
165 gpu_write(gpu, REG_A4XX_VBIF_IN_WR_LIM_CONF1, 0x00000018);
166 gpu_write(gpu, REG_A4XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x00000003);
Aravind Ganesan23bd62f2014-09-08 13:40:16 -0600167 } else {
168 BUG();
169 }
170
171 /* Make all blocks contribute to the GPU BUSY perf counter */
172 gpu_write(gpu, REG_A4XX_RBBM_GPU_BUSY_MASKED, 0xffffffff);
173
174 /* Tune the hystersis counters for SP and CP idle detection */
175 gpu_write(gpu, REG_A4XX_RBBM_SP_HYST_CNT, 0x10);
176 gpu_write(gpu, REG_A4XX_RBBM_WAIT_IDLE_CLOCKS_CTL, 0x10);
177
Craig Stout357ff002016-02-18 16:50:00 -0800178 if (adreno_is_a430(adreno_gpu)) {
179 gpu_write(gpu, REG_A4XX_RBBM_WAIT_IDLE_CLOCKS_CTL2, 0x30);
180 }
181
Aravind Ganesan23bd62f2014-09-08 13:40:16 -0600182 /* Enable the RBBM error reporting bits */
183 gpu_write(gpu, REG_A4XX_RBBM_AHB_CTL0, 0x00000001);
184
185 /* Enable AHB error reporting*/
186 gpu_write(gpu, REG_A4XX_RBBM_AHB_CTL1, 0xa6ffffff);
187
188 /* Enable power counters*/
189 gpu_write(gpu, REG_A4XX_RBBM_RBBM_CTL, 0x00000030);
190
191 /*
192 * Turn on hang detection - this spews a lot of useful information
193 * into the RBBM registers on a hang:
194 */
195 gpu_write(gpu, REG_A4XX_RBBM_INTERFACE_HANG_INT_CTL,
196 (1 << 30) | 0xFFFF);
197
198 gpu_write(gpu, REG_A4XX_RB_GMEM_BASE_ADDR,
199 (unsigned int)(a4xx_gpu->ocmem_base >> 14));
200
201 /* Turn on performance counters: */
202 gpu_write(gpu, REG_A4XX_RBBM_PERFCTR_CTL, 0x01);
203
Rob Clark6c77d1a2016-02-22 06:26:21 -0500204 /* use the first CP counter for timestamp queries.. userspace may set
205 * this as well but it selects the same counter/countable:
206 */
207 gpu_write(gpu, REG_A4XX_CP_PERFCTR_CP_SEL_0, CP_ALWAYS_COUNT);
208
Craig Stout357ff002016-02-18 16:50:00 -0800209 if (adreno_is_a430(adreno_gpu))
210 gpu_write(gpu, REG_A4XX_UCHE_CACHE_WAYS_VFD, 0x07);
211
Aravind Ganesan23bd62f2014-09-08 13:40:16 -0600212 /* Disable L2 bypass to avoid UCHE out of bounds errors */
213 gpu_write(gpu, REG_A4XX_UCHE_TRAP_BASE_LO, 0xffff0000);
214 gpu_write(gpu, REG_A4XX_UCHE_TRAP_BASE_HI, 0xffff0000);
215
216 gpu_write(gpu, REG_A4XX_CP_DEBUG, (1 << 25) |
217 (adreno_is_a420(adreno_gpu) ? (1 << 29) : 0));
218
Craig Stout357ff002016-02-18 16:50:00 -0800219 /* On A430 enable SP regfile sleep for power savings */
220 /* TODO downstream does this for !420, so maybe applies for 405 too? */
221 if (!adreno_is_a420(adreno_gpu)) {
222 gpu_write(gpu, REG_A4XX_RBBM_SP_REGFILE_SLEEP_CNTL_0,
223 0x00000441);
224 gpu_write(gpu, REG_A4XX_RBBM_SP_REGFILE_SLEEP_CNTL_1,
225 0x00000441);
226 }
227
Aravind Ganesan23bd62f2014-09-08 13:40:16 -0600228 a4xx_enable_hwcg(gpu);
229
230 /*
231 * For A420 set RBBM_CLOCK_DELAY_HLSQ.CGC_HLSQ_TP_EARLY_CYC >= 2
232 * due to timing issue with HLSQ_TP_CLK_EN
233 */
234 if (adreno_is_a420(adreno_gpu)) {
235 unsigned int val;
236 val = gpu_read(gpu, REG_A4XX_RBBM_CLOCK_DELAY_HLSQ);
237 val &= ~A4XX_CGC_HLSQ_EARLY_CYC__MASK;
238 val |= 2 << A4XX_CGC_HLSQ_EARLY_CYC__SHIFT;
239 gpu_write(gpu, REG_A4XX_RBBM_CLOCK_DELAY_HLSQ, val);
240 }
241
Aravind Ganesan23bd62f2014-09-08 13:40:16 -0600242 /* setup access protection: */
243 gpu_write(gpu, REG_A4XX_CP_PROTECT_CTRL, 0x00000007);
244
245 /* RBBM registers */
246 gpu_write(gpu, REG_A4XX_CP_PROTECT(0), 0x62000010);
247 gpu_write(gpu, REG_A4XX_CP_PROTECT(1), 0x63000020);
248 gpu_write(gpu, REG_A4XX_CP_PROTECT(2), 0x64000040);
249 gpu_write(gpu, REG_A4XX_CP_PROTECT(3), 0x65000080);
250 gpu_write(gpu, REG_A4XX_CP_PROTECT(4), 0x66000100);
251 gpu_write(gpu, REG_A4XX_CP_PROTECT(5), 0x64000200);
252
253 /* CP registers */
254 gpu_write(gpu, REG_A4XX_CP_PROTECT(6), 0x67000800);
255 gpu_write(gpu, REG_A4XX_CP_PROTECT(7), 0x64001600);
256
257
258 /* RB registers */
259 gpu_write(gpu, REG_A4XX_CP_PROTECT(8), 0x60003300);
260
261 /* HLSQ registers */
262 gpu_write(gpu, REG_A4XX_CP_PROTECT(9), 0x60003800);
263
264 /* VPC registers */
265 gpu_write(gpu, REG_A4XX_CP_PROTECT(10), 0x61003980);
266
267 /* SMMU registers */
268 gpu_write(gpu, REG_A4XX_CP_PROTECT(11), 0x6e010000);
269
270 gpu_write(gpu, REG_A4XX_RBBM_INT_0_MASK, A4XX_INT0_MASK);
271
272 ret = adreno_hw_init(gpu);
273 if (ret)
274 return ret;
275
276 /* Load PM4: */
277 ptr = (uint32_t *)(adreno_gpu->pm4->data);
278 len = adreno_gpu->pm4->size / 4;
279 DBG("loading PM4 ucode version: %u", ptr[0]);
280 gpu_write(gpu, REG_A4XX_CP_ME_RAM_WADDR, 0);
281 for (i = 1; i < len; i++)
282 gpu_write(gpu, REG_A4XX_CP_ME_RAM_DATA, ptr[i]);
283
284 /* Load PFP: */
285 ptr = (uint32_t *)(adreno_gpu->pfp->data);
286 len = adreno_gpu->pfp->size / 4;
287 DBG("loading PFP ucode version: %u", ptr[0]);
288
289 gpu_write(gpu, REG_A4XX_CP_PFP_UCODE_ADDR, 0);
290 for (i = 1; i < len; i++)
291 gpu_write(gpu, REG_A4XX_CP_PFP_UCODE_DATA, ptr[i]);
292
293 /* clear ME_HALT to start micro engine */
294 gpu_write(gpu, REG_A4XX_CP_ME_CNTL, 0);
295
Jordan Crousec4a8d4752016-11-28 12:28:27 -0700296 return a4xx_me_init(gpu) ? 0 : -EINVAL;
Aravind Ganesan23bd62f2014-09-08 13:40:16 -0600297}
298
299static void a4xx_recover(struct msm_gpu *gpu)
300{
Rob Clark398efc42016-11-11 14:46:00 -0500301 int i;
302
Rob Clark26716182015-04-19 10:14:09 -0400303 adreno_dump_info(gpu);
304
Rob Clark398efc42016-11-11 14:46:00 -0500305 for (i = 0; i < 8; i++) {
306 printk("CP_SCRATCH_REG%d: %u\n", i,
307 gpu_read(gpu, REG_AXXX_CP_SCRATCH_REG0 + i));
308 }
309
Aravind Ganesan23bd62f2014-09-08 13:40:16 -0600310 /* dump registers before resetting gpu, if enabled: */
311 if (hang_debug)
312 a4xx_dump(gpu);
313
314 gpu_write(gpu, REG_A4XX_RBBM_SW_RESET_CMD, 1);
315 gpu_read(gpu, REG_A4XX_RBBM_SW_RESET_CMD);
316 gpu_write(gpu, REG_A4XX_RBBM_SW_RESET_CMD, 0);
317 adreno_recover(gpu);
318}
319
320static void a4xx_destroy(struct msm_gpu *gpu)
321{
322 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
323 struct a4xx_gpu *a4xx_gpu = to_a4xx_gpu(adreno_gpu);
324
325 DBG("%s", gpu->name);
326
327 adreno_gpu_cleanup(adreno_gpu);
328
329#ifdef CONFIG_MSM_OCMEM
330 if (a4xx_gpu->ocmem_base)
331 ocmem_free(OCMEM_GRAPHICS, a4xx_gpu->ocmem_hdl);
332#endif
333
334 kfree(a4xx_gpu);
335}
336
Jordan Crousec4a8d4752016-11-28 12:28:27 -0700337static bool a4xx_idle(struct msm_gpu *gpu)
Aravind Ganesan23bd62f2014-09-08 13:40:16 -0600338{
339 /* wait for ringbuffer to drain: */
Jordan Crousef97deca2017-10-20 11:06:57 -0600340 if (!adreno_idle(gpu, gpu->rb[0]))
Jordan Crousec4a8d4752016-11-28 12:28:27 -0700341 return false;
Aravind Ganesan23bd62f2014-09-08 13:40:16 -0600342
343 /* then wait for GPU to finish: */
344 if (spin_until(!(gpu_read(gpu, REG_A4XX_RBBM_STATUS) &
Jordan Crousec4a8d4752016-11-28 12:28:27 -0700345 A4XX_RBBM_STATUS_GPU_BUSY))) {
Aravind Ganesan23bd62f2014-09-08 13:40:16 -0600346 DRM_ERROR("%s: timeout waiting for GPU to idle!\n", gpu->name);
Jordan Crousec4a8d4752016-11-28 12:28:27 -0700347 /* TODO maybe we need to reset GPU here to recover from hang? */
348 return false;
349 }
Aravind Ganesan23bd62f2014-09-08 13:40:16 -0600350
Jordan Crousec4a8d4752016-11-28 12:28:27 -0700351 return true;
Aravind Ganesan23bd62f2014-09-08 13:40:16 -0600352}
353
354static irqreturn_t a4xx_irq(struct msm_gpu *gpu)
355{
356 uint32_t status;
357
358 status = gpu_read(gpu, REG_A4XX_RBBM_INT_0_STATUS);
359 DBG("%s: Int status %08x", gpu->name, status);
360
Craig Stout1e2c8e72016-02-18 16:50:03 -0800361 if (status & A4XX_INT0_CP_REG_PROTECT_FAULT) {
362 uint32_t reg = gpu_read(gpu, REG_A4XX_CP_PROTECT_STATUS);
363 printk("CP | Protected mode error| %s | addr=%x\n",
364 reg & (1 << 24) ? "WRITE" : "READ",
365 (reg & 0xFFFFF) >> 2);
366 }
367
Aravind Ganesan23bd62f2014-09-08 13:40:16 -0600368 gpu_write(gpu, REG_A4XX_RBBM_INT_CLEAR_CMD, status);
369
370 msm_gpu_retire(gpu);
371
372 return IRQ_HANDLED;
373}
374
375static const unsigned int a4xx_registers[] = {
376 /* RBBM */
377 0x0000, 0x0002, 0x0004, 0x0021, 0x0023, 0x0024, 0x0026, 0x0026,
378 0x0028, 0x002B, 0x002E, 0x0034, 0x0037, 0x0044, 0x0047, 0x0066,
379 0x0068, 0x0095, 0x009C, 0x0170, 0x0174, 0x01AF,
380 /* CP */
381 0x0200, 0x0233, 0x0240, 0x0250, 0x04C0, 0x04DD, 0x0500, 0x050B,
382 0x0578, 0x058F,
383 /* VSC */
384 0x0C00, 0x0C03, 0x0C08, 0x0C41, 0x0C50, 0x0C51,
385 /* GRAS */
386 0x0C80, 0x0C81, 0x0C88, 0x0C8F,
387 /* RB */
388 0x0CC0, 0x0CC0, 0x0CC4, 0x0CD2,
389 /* PC */
390 0x0D00, 0x0D0C, 0x0D10, 0x0D17, 0x0D20, 0x0D23,
391 /* VFD */
392 0x0E40, 0x0E4A,
393 /* VPC */
394 0x0E60, 0x0E61, 0x0E63, 0x0E68,
395 /* UCHE */
396 0x0E80, 0x0E84, 0x0E88, 0x0E95,
397 /* VMIDMT */
398 0x1000, 0x1000, 0x1002, 0x1002, 0x1004, 0x1004, 0x1008, 0x100A,
399 0x100C, 0x100D, 0x100F, 0x1010, 0x1012, 0x1016, 0x1024, 0x1024,
400 0x1027, 0x1027, 0x1100, 0x1100, 0x1102, 0x1102, 0x1104, 0x1104,
401 0x1110, 0x1110, 0x1112, 0x1116, 0x1124, 0x1124, 0x1300, 0x1300,
402 0x1380, 0x1380,
403 /* GRAS CTX 0 */
404 0x2000, 0x2004, 0x2008, 0x2067, 0x2070, 0x2078, 0x207B, 0x216E,
405 /* PC CTX 0 */
406 0x21C0, 0x21C6, 0x21D0, 0x21D0, 0x21D9, 0x21D9, 0x21E5, 0x21E7,
407 /* VFD CTX 0 */
408 0x2200, 0x2204, 0x2208, 0x22A9,
409 /* GRAS CTX 1 */
410 0x2400, 0x2404, 0x2408, 0x2467, 0x2470, 0x2478, 0x247B, 0x256E,
411 /* PC CTX 1 */
412 0x25C0, 0x25C6, 0x25D0, 0x25D0, 0x25D9, 0x25D9, 0x25E5, 0x25E7,
413 /* VFD CTX 1 */
414 0x2600, 0x2604, 0x2608, 0x26A9,
415 /* XPU */
416 0x2C00, 0x2C01, 0x2C10, 0x2C10, 0x2C12, 0x2C16, 0x2C1D, 0x2C20,
417 0x2C28, 0x2C28, 0x2C30, 0x2C30, 0x2C32, 0x2C36, 0x2C40, 0x2C40,
418 0x2C50, 0x2C50, 0x2C52, 0x2C56, 0x2C80, 0x2C80, 0x2C94, 0x2C95,
419 /* VBIF */
420 0x3000, 0x3007, 0x300C, 0x3014, 0x3018, 0x301D, 0x3020, 0x3022,
421 0x3024, 0x3026, 0x3028, 0x302A, 0x302C, 0x302D, 0x3030, 0x3031,
422 0x3034, 0x3036, 0x3038, 0x3038, 0x303C, 0x303D, 0x3040, 0x3040,
423 0x3049, 0x3049, 0x3058, 0x3058, 0x305B, 0x3061, 0x3064, 0x3068,
424 0x306C, 0x306D, 0x3080, 0x3088, 0x308B, 0x308C, 0x3090, 0x3094,
425 0x3098, 0x3098, 0x309C, 0x309C, 0x30C0, 0x30C0, 0x30C8, 0x30C8,
426 0x30D0, 0x30D0, 0x30D8, 0x30D8, 0x30E0, 0x30E0, 0x3100, 0x3100,
427 0x3108, 0x3108, 0x3110, 0x3110, 0x3118, 0x3118, 0x3120, 0x3120,
428 0x3124, 0x3125, 0x3129, 0x3129, 0x3131, 0x3131, 0x330C, 0x330C,
429 0x3310, 0x3310, 0x3400, 0x3401, 0x3410, 0x3410, 0x3412, 0x3416,
430 0x341D, 0x3420, 0x3428, 0x3428, 0x3430, 0x3430, 0x3432, 0x3436,
431 0x3440, 0x3440, 0x3450, 0x3450, 0x3452, 0x3456, 0x3480, 0x3480,
432 0x3494, 0x3495, 0x4000, 0x4000, 0x4002, 0x4002, 0x4004, 0x4004,
433 0x4008, 0x400A, 0x400C, 0x400D, 0x400F, 0x4012, 0x4014, 0x4016,
434 0x401D, 0x401D, 0x4020, 0x4027, 0x4060, 0x4062, 0x4200, 0x4200,
435 0x4300, 0x4300, 0x4400, 0x4400, 0x4500, 0x4500, 0x4800, 0x4802,
436 0x480F, 0x480F, 0x4811, 0x4811, 0x4813, 0x4813, 0x4815, 0x4816,
437 0x482B, 0x482B, 0x4857, 0x4857, 0x4883, 0x4883, 0x48AF, 0x48AF,
438 0x48C5, 0x48C5, 0x48E5, 0x48E5, 0x4905, 0x4905, 0x4925, 0x4925,
439 0x4945, 0x4945, 0x4950, 0x4950, 0x495B, 0x495B, 0x4980, 0x498E,
440 0x4B00, 0x4B00, 0x4C00, 0x4C00, 0x4D00, 0x4D00, 0x4E00, 0x4E00,
441 0x4E80, 0x4E80, 0x4F00, 0x4F00, 0x4F08, 0x4F08, 0x4F10, 0x4F10,
442 0x4F18, 0x4F18, 0x4F20, 0x4F20, 0x4F30, 0x4F30, 0x4F60, 0x4F60,
443 0x4F80, 0x4F81, 0x4F88, 0x4F89, 0x4FEE, 0x4FEE, 0x4FF3, 0x4FF3,
444 0x6000, 0x6001, 0x6008, 0x600F, 0x6014, 0x6016, 0x6018, 0x601B,
445 0x61FD, 0x61FD, 0x623C, 0x623C, 0x6380, 0x6380, 0x63A0, 0x63A0,
446 0x63C0, 0x63C1, 0x63C8, 0x63C9, 0x63D0, 0x63D4, 0x63D6, 0x63D6,
447 0x63EE, 0x63EE, 0x6400, 0x6401, 0x6408, 0x640F, 0x6414, 0x6416,
448 0x6418, 0x641B, 0x65FD, 0x65FD, 0x663C, 0x663C, 0x6780, 0x6780,
449 0x67A0, 0x67A0, 0x67C0, 0x67C1, 0x67C8, 0x67C9, 0x67D0, 0x67D4,
450 0x67D6, 0x67D6, 0x67EE, 0x67EE, 0x6800, 0x6801, 0x6808, 0x680F,
451 0x6814, 0x6816, 0x6818, 0x681B, 0x69FD, 0x69FD, 0x6A3C, 0x6A3C,
452 0x6B80, 0x6B80, 0x6BA0, 0x6BA0, 0x6BC0, 0x6BC1, 0x6BC8, 0x6BC9,
453 0x6BD0, 0x6BD4, 0x6BD6, 0x6BD6, 0x6BEE, 0x6BEE,
454 ~0 /* sentinel */
455};
456
457#ifdef CONFIG_DEBUG_FS
458static void a4xx_show(struct msm_gpu *gpu, struct seq_file *m)
459{
Aravind Ganesan23bd62f2014-09-08 13:40:16 -0600460 seq_printf(m, "status: %08x\n",
461 gpu_read(gpu, REG_A4XX_RBBM_STATUS));
Aravind Ganesan23bd62f2014-09-08 13:40:16 -0600462 adreno_show(gpu, m);
463
464}
465#endif
466
467/* Register offset defines for A4XX, in order of enum adreno_regs */
468static const unsigned int a4xx_register_offsets[REG_ADRENO_REGISTER_MAX] = {
Aravind Ganesan23bd62f2014-09-08 13:40:16 -0600469 REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_BASE, REG_A4XX_CP_RB_BASE),
Jordan Crousefb039982016-11-28 12:28:29 -0700470 REG_ADRENO_SKIP(REG_ADRENO_CP_RB_BASE_HI),
Aravind Ganesan23bd62f2014-09-08 13:40:16 -0600471 REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_RPTR_ADDR, REG_A4XX_CP_RB_RPTR_ADDR),
Jordan Crousefb039982016-11-28 12:28:29 -0700472 REG_ADRENO_SKIP(REG_ADRENO_CP_RB_RPTR_ADDR_HI),
Aravind Ganesan23bd62f2014-09-08 13:40:16 -0600473 REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_RPTR, REG_A4XX_CP_RB_RPTR),
474 REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_WPTR, REG_A4XX_CP_RB_WPTR),
Aravind Ganesan23bd62f2014-09-08 13:40:16 -0600475 REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_CNTL, REG_A4XX_CP_RB_CNTL),
Aravind Ganesan23bd62f2014-09-08 13:40:16 -0600476};
477
478static void a4xx_dump(struct msm_gpu *gpu)
479{
Aravind Ganesan23bd62f2014-09-08 13:40:16 -0600480 printk("status: %08x\n",
481 gpu_read(gpu, REG_A4XX_RBBM_STATUS));
482 adreno_dump(gpu);
483}
484
Craig Stout38bbc552016-02-18 16:50:01 -0800485static int a4xx_pm_resume(struct msm_gpu *gpu) {
486 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
487 int ret;
488
489 ret = msm_gpu_pm_resume(gpu);
490 if (ret)
491 return ret;
492
493 if (adreno_is_a430(adreno_gpu)) {
494 unsigned int reg;
495 /* Set the default register values; set SW_COLLAPSE to 0 */
496 gpu_write(gpu, REG_A4XX_RBBM_POWER_CNTL_IP, 0x778000);
497 do {
498 udelay(5);
499 reg = gpu_read(gpu, REG_A4XX_RBBM_POWER_STATUS);
500 } while (!(reg & A4XX_RBBM_POWER_CNTL_IP_SP_TP_PWR_ON));
501 }
502 return 0;
503}
504
505static int a4xx_pm_suspend(struct msm_gpu *gpu) {
506 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
507 int ret;
508
509 ret = msm_gpu_pm_suspend(gpu);
510 if (ret)
511 return ret;
512
513 if (adreno_is_a430(adreno_gpu)) {
514 /* Set the default register values; set SW_COLLAPSE to 1 */
515 gpu_write(gpu, REG_A4XX_RBBM_POWER_CNTL_IP, 0x778001);
516 }
517 return 0;
518}
519
Rob Clark6c77d1a2016-02-22 06:26:21 -0500520static int a4xx_get_timestamp(struct msm_gpu *gpu, uint64_t *value)
521{
Jordan Crouseae53a822016-11-28 12:28:28 -0700522 *value = gpu_read64(gpu, REG_A4XX_RBBM_PERFCTR_CP_0_LO,
523 REG_A4XX_RBBM_PERFCTR_CP_0_HI);
Rob Clark6c77d1a2016-02-22 06:26:21 -0500524
525 return 0;
526}
527
Aravind Ganesan23bd62f2014-09-08 13:40:16 -0600528static const struct adreno_gpu_funcs funcs = {
529 .base = {
530 .get_param = adreno_get_param,
531 .hw_init = a4xx_hw_init,
Craig Stout38bbc552016-02-18 16:50:01 -0800532 .pm_suspend = a4xx_pm_suspend,
533 .pm_resume = a4xx_pm_resume,
Aravind Ganesan23bd62f2014-09-08 13:40:16 -0600534 .recover = a4xx_recover,
Aravind Ganesan23bd62f2014-09-08 13:40:16 -0600535 .submit = adreno_submit,
536 .flush = adreno_flush,
Jordan Crousef97deca2017-10-20 11:06:57 -0600537 .active_ring = adreno_active_ring,
Aravind Ganesan23bd62f2014-09-08 13:40:16 -0600538 .irq = a4xx_irq,
539 .destroy = a4xx_destroy,
540#ifdef CONFIG_DEBUG_FS
541 .show = a4xx_show,
542#endif
543 },
Rob Clark6c77d1a2016-02-22 06:26:21 -0500544 .get_timestamp = a4xx_get_timestamp,
Aravind Ganesan23bd62f2014-09-08 13:40:16 -0600545};
546
547struct msm_gpu *a4xx_gpu_init(struct drm_device *dev)
548{
549 struct a4xx_gpu *a4xx_gpu = NULL;
550 struct adreno_gpu *adreno_gpu;
551 struct msm_gpu *gpu;
552 struct msm_drm_private *priv = dev->dev_private;
553 struct platform_device *pdev = priv->gpu_pdev;
554 int ret;
555
556 if (!pdev) {
557 dev_err(dev->dev, "no a4xx device\n");
558 ret = -ENXIO;
559 goto fail;
560 }
561
562 a4xx_gpu = kzalloc(sizeof(*a4xx_gpu), GFP_KERNEL);
563 if (!a4xx_gpu) {
564 ret = -ENOMEM;
565 goto fail;
566 }
567
568 adreno_gpu = &a4xx_gpu->base;
569 gpu = &adreno_gpu->base;
570
Aravind Ganesan23bd62f2014-09-08 13:40:16 -0600571 gpu->perfcntrs = NULL;
572 gpu->num_perfcntrs = 0;
573
574 adreno_gpu->registers = a4xx_registers;
575 adreno_gpu->reg_offsets = a4xx_register_offsets;
576
Jordan Crousef97deca2017-10-20 11:06:57 -0600577 ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 1);
Aravind Ganesan23bd62f2014-09-08 13:40:16 -0600578 if (ret)
579 goto fail;
580
581 /* if needed, allocate gmem: */
582 if (adreno_is_a4xx(adreno_gpu)) {
583#ifdef CONFIG_MSM_OCMEM
584 /* TODO this is different/missing upstream: */
585 struct ocmem_buf *ocmem_hdl =
586 ocmem_allocate(OCMEM_GRAPHICS, adreno_gpu->gmem);
587
588 a4xx_gpu->ocmem_hdl = ocmem_hdl;
589 a4xx_gpu->ocmem_base = ocmem_hdl->addr;
590 adreno_gpu->gmem = ocmem_hdl->len;
591 DBG("using %dK of OCMEM at 0x%08x", adreno_gpu->gmem / 1024,
592 a4xx_gpu->ocmem_base);
593#endif
594 }
595
Rob Clark667ce332016-09-28 19:58:32 -0400596 if (!gpu->aspace) {
Aravind Ganesan23bd62f2014-09-08 13:40:16 -0600597 /* TODO we think it is possible to configure the GPU to
598 * restrict access to VRAM carveout. But the required
599 * registers are unknown. For now just bail out and
600 * limp along with just modesetting. If it turns out
601 * to not be possible to restrict access, then we must
602 * implement a cmdstream validator.
603 */
604 dev_err(dev->dev, "No memory protection without IOMMU\n");
605 ret = -ENXIO;
606 goto fail;
607 }
608
609 return gpu;
610
611fail:
612 if (a4xx_gpu)
613 a4xx_destroy(&a4xx_gpu->base.base);
614
615 return ERR_PTR(ret);
616}