1// SPDX-License-Identifier: GPL-2.0
2/* Copyright (c) 2018 The Linux Foundation. All rights reserved. */
3
4#include "a2xx_gpu.h"
5#include "msm_gem.h"
6#include "msm_mmu.h"
7
8extern bool hang_debug;
9
10static void a2xx_dump(struct msm_gpu *gpu);
11static bool a2xx_idle(struct msm_gpu *gpu);
12
13static void a2xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
14{
15 struct msm_ringbuffer *ring = submit->ring;
16 unsigned int i;
17
18 for (i = 0; i < submit->nr_cmds; i++) {
19 switch (submit->cmd[i].type) {
20 case MSM_SUBMIT_CMD_IB_TARGET_BUF:
21 /* ignore IB-targets */
22 break;
23 case MSM_SUBMIT_CMD_CTX_RESTORE_BUF:
24 /* ignore if there has not been a ctx switch: */
25 if (gpu->cur_ctx_seqno == submit->queue->ctx->seqno)
26 break;
27 fallthrough;
28 case MSM_SUBMIT_CMD_BUF:
29 OUT_PKT3(ring, opcode: CP_INDIRECT_BUFFER_PFD, cnt: 2);
30 OUT_RING(ring, lower_32_bits(submit->cmd[i].iova));
31 OUT_RING(ring, submit->cmd[i].size);
32 OUT_PKT2(ring);
33 break;
34 }
35 }
36
37 OUT_PKT0(ring, REG_AXXX_CP_SCRATCH_REG2, cnt: 1);
38 OUT_RING(ring, submit->seqno);
39
40 /* wait for idle before cache flush/interrupt */
41 OUT_PKT3(ring, opcode: CP_WAIT_FOR_IDLE, cnt: 1);
42 OUT_RING(ring, 0x00000000);
43
44 OUT_PKT3(ring, opcode: CP_EVENT_WRITE, cnt: 3);
45 OUT_RING(ring, CACHE_FLUSH_TS);
46 OUT_RING(ring, rbmemptr(ring, fence));
47 OUT_RING(ring, submit->seqno);
48 OUT_PKT3(ring, opcode: CP_INTERRUPT, cnt: 1);
49 OUT_RING(ring, 0x80000000);
50
51 adreno_flush(gpu, ring, REG_AXXX_CP_RB_WPTR);
52}
53
54static bool a2xx_me_init(struct msm_gpu *gpu)
55{
56 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
57 struct a2xx_gpu *a2xx_gpu = to_a2xx_gpu(adreno_gpu);
58 struct msm_ringbuffer *ring = gpu->rb[0];
59
60 OUT_PKT3(ring, opcode: CP_ME_INIT, cnt: 18);
61
62 /* All fields present (bits 9:0) */
63 OUT_RING(ring, 0x000003ff);
64 /* Disable/Enable Real-Time Stream processing (present but ignored) */
65 OUT_RING(ring, 0x00000000);
66 /* Enable (2D <-> 3D) implicit synchronization (present but ignored) */
67 OUT_RING(ring, 0x00000000);
68
69 OUT_RING(ring, REG_A2XX_RB_SURFACE_INFO - 0x2000);
70 OUT_RING(ring, REG_A2XX_PA_SC_WINDOW_OFFSET - 0x2000);
71 OUT_RING(ring, REG_A2XX_VGT_MAX_VTX_INDX - 0x2000);
72 OUT_RING(ring, REG_A2XX_SQ_PROGRAM_CNTL - 0x2000);
73 OUT_RING(ring, REG_A2XX_RB_DEPTHCONTROL - 0x2000);
74 OUT_RING(ring, REG_A2XX_PA_SU_POINT_SIZE - 0x2000);
75 OUT_RING(ring, REG_A2XX_PA_SC_LINE_CNTL - 0x2000);
76 OUT_RING(ring, REG_A2XX_PA_SU_POLY_OFFSET_FRONT_SCALE - 0x2000);
77
78 /* Vertex and Pixel Shader Start Addresses in instructions
79 * (3 DWORDS per instruction) */
80 OUT_RING(ring, 0x80000180);
81 /* Maximum Contexts */
82 OUT_RING(ring, 0x00000001);
83 /* Write Confirm Interval and The CP will wait the
84 * wait_interval * 16 clocks between polling */
85 OUT_RING(ring, 0x00000000);
86 /* NQ and External Memory Swap */
87 OUT_RING(ring, 0x00000000);
88 /* protected mode error checking (0x1f2 is REG_AXXX_CP_INT_CNTL) */
89 if (a2xx_gpu->protection_disabled)
90 OUT_RING(ring, 0x00000000);
91 else
92 OUT_RING(ring, 0x200001f2);
93 /* Disable header dumping and Header dump address */
94 OUT_RING(ring, 0x00000000);
95 /* Header dump size */
96 OUT_RING(ring, 0x00000000);
97
98 if (!a2xx_gpu->protection_disabled) {
99 /* enable protected mode */
100 OUT_PKT3(ring, opcode: CP_SET_PROTECTED_MODE, cnt: 1);
101 OUT_RING(ring, 1);
102 }
103
104 adreno_flush(gpu, ring, REG_AXXX_CP_RB_WPTR);
105 return a2xx_idle(gpu);
106}
107
108static int a2xx_hw_init(struct msm_gpu *gpu)
109{
110 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
111 struct a2xx_gpu *a2xx_gpu = to_a2xx_gpu(adreno_gpu);
112 dma_addr_t pt_base, tran_error;
113 uint32_t *ptr, len;
114 int i, ret;
115
116 msm_gpummu_params(gpu->aspace->mmu, &pt_base, &tran_error);
117
118 DBG("%s", gpu->name);
119
120 /* halt ME to avoid ucode upload issues on a20x */
121 gpu_write(gpu, REG_AXXX_CP_ME_CNTL, AXXX_CP_ME_CNTL_HALT);
122
123 gpu_write(gpu, REG_A2XX_RBBM_PM_OVERRIDE1, 0xfffffffe);
124 gpu_write(gpu, REG_A2XX_RBBM_PM_OVERRIDE2, 0xffffffff);
125
126 /* note: kgsl uses 0x00000001 after first reset on a22x */
127 gpu_write(gpu, REG_A2XX_RBBM_SOFT_RESET, 0xffffffff);
128 msleep(msecs: 30);
129 gpu_write(gpu, REG_A2XX_RBBM_SOFT_RESET, 0x00000000);
130
131 if (adreno_is_a225(gpu: adreno_gpu))
132 gpu_write(gpu, REG_A2XX_SQ_FLOW_CONTROL, 0x18000000);
133
134 /* note: kgsl uses 0x0000ffff for a20x */
135 gpu_write(gpu, REG_A2XX_RBBM_CNTL, 0x00004442);
136
137 /* MPU: physical range */
138 gpu_write(gpu, REG_A2XX_MH_MMU_MPU_BASE, 0x00000000);
139 gpu_write(gpu, REG_A2XX_MH_MMU_MPU_END, 0xfffff000);
140
141 gpu_write(gpu, REG_A2XX_MH_MMU_CONFIG, A2XX_MH_MMU_CONFIG_MMU_ENABLE |
142 A2XX_MH_MMU_CONFIG_RB_W_CLNT_BEHAVIOR(val: BEH_TRAN_RNG) |
143 A2XX_MH_MMU_CONFIG_CP_W_CLNT_BEHAVIOR(val: BEH_TRAN_RNG) |
144 A2XX_MH_MMU_CONFIG_CP_R0_CLNT_BEHAVIOR(val: BEH_TRAN_RNG) |
145 A2XX_MH_MMU_CONFIG_CP_R1_CLNT_BEHAVIOR(val: BEH_TRAN_RNG) |
146 A2XX_MH_MMU_CONFIG_CP_R2_CLNT_BEHAVIOR(val: BEH_TRAN_RNG) |
147 A2XX_MH_MMU_CONFIG_CP_R3_CLNT_BEHAVIOR(val: BEH_TRAN_RNG) |
148 A2XX_MH_MMU_CONFIG_CP_R4_CLNT_BEHAVIOR(val: BEH_TRAN_RNG) |
149 A2XX_MH_MMU_CONFIG_VGT_R0_CLNT_BEHAVIOR(val: BEH_TRAN_RNG) |
150 A2XX_MH_MMU_CONFIG_VGT_R1_CLNT_BEHAVIOR(val: BEH_TRAN_RNG) |
151 A2XX_MH_MMU_CONFIG_TC_R_CLNT_BEHAVIOR(val: BEH_TRAN_RNG) |
152 A2XX_MH_MMU_CONFIG_PA_W_CLNT_BEHAVIOR(val: BEH_TRAN_RNG));
153
154 /* same as parameters in adreno_gpu */
155 gpu_write(gpu, REG_A2XX_MH_MMU_VA_RANGE, SZ_16M |
156 A2XX_MH_MMU_VA_RANGE_NUM_64KB_REGIONS(val: 0xfff));
157
158 gpu_write(gpu, REG_A2XX_MH_MMU_PT_BASE, pt_base);
159 gpu_write(gpu, REG_A2XX_MH_MMU_TRAN_ERROR, tran_error);
160
161 gpu_write(gpu, REG_A2XX_MH_MMU_INVALIDATE,
162 A2XX_MH_MMU_INVALIDATE_INVALIDATE_ALL |
163 A2XX_MH_MMU_INVALIDATE_INVALIDATE_TC);
164
165 gpu_write(gpu, REG_A2XX_MH_ARBITER_CONFIG,
166 A2XX_MH_ARBITER_CONFIG_SAME_PAGE_LIMIT(val: 16) |
167 A2XX_MH_ARBITER_CONFIG_L1_ARB_ENABLE |
168 A2XX_MH_ARBITER_CONFIG_L1_ARB_HOLD_ENABLE |
169 A2XX_MH_ARBITER_CONFIG_PAGE_SIZE(val: 1) |
170 A2XX_MH_ARBITER_CONFIG_TC_REORDER_ENABLE |
171 A2XX_MH_ARBITER_CONFIG_TC_ARB_HOLD_ENABLE |
172 A2XX_MH_ARBITER_CONFIG_IN_FLIGHT_LIMIT_ENABLE |
173 A2XX_MH_ARBITER_CONFIG_IN_FLIGHT_LIMIT(val: 8) |
174 A2XX_MH_ARBITER_CONFIG_CP_CLNT_ENABLE |
175 A2XX_MH_ARBITER_CONFIG_VGT_CLNT_ENABLE |
176 A2XX_MH_ARBITER_CONFIG_TC_CLNT_ENABLE |
177 A2XX_MH_ARBITER_CONFIG_RB_CLNT_ENABLE |
178 A2XX_MH_ARBITER_CONFIG_PA_CLNT_ENABLE);
179 if (!adreno_is_a20x(gpu: adreno_gpu))
180 gpu_write(gpu, REG_A2XX_MH_CLNT_INTF_CTRL_CONFIG1, 0x00032f07);
181
182 gpu_write(gpu, REG_A2XX_SQ_VS_PROGRAM, 0x00000000);
183 gpu_write(gpu, REG_A2XX_SQ_PS_PROGRAM, 0x00000000);
184
185 gpu_write(gpu, REG_A2XX_RBBM_PM_OVERRIDE1, 0); /* 0x200 for msm8960? */
186 gpu_write(gpu, REG_A2XX_RBBM_PM_OVERRIDE2, 0); /* 0x80/0x1a0 for a22x? */
187
188 /* note: gsl doesn't set this */
189 gpu_write(gpu, REG_A2XX_RBBM_DEBUG, 0x00080000);
190
191 gpu_write(gpu, REG_A2XX_RBBM_INT_CNTL,
192 A2XX_RBBM_INT_CNTL_RDERR_INT_MASK);
193 gpu_write(gpu, REG_AXXX_CP_INT_CNTL,
194 AXXX_CP_INT_CNTL_T0_PACKET_IN_IB_MASK |
195 AXXX_CP_INT_CNTL_OPCODE_ERROR_MASK |
196 AXXX_CP_INT_CNTL_PROTECTED_MODE_ERROR_MASK |
197 AXXX_CP_INT_CNTL_RESERVED_BIT_ERROR_MASK |
198 AXXX_CP_INT_CNTL_IB_ERROR_MASK |
199 AXXX_CP_INT_CNTL_IB1_INT_MASK |
200 AXXX_CP_INT_CNTL_RB_INT_MASK);
201 gpu_write(gpu, REG_A2XX_SQ_INT_CNTL, 0);
202 gpu_write(gpu, REG_A2XX_MH_INTERRUPT_MASK,
203 A2XX_MH_INTERRUPT_MASK_AXI_READ_ERROR |
204 A2XX_MH_INTERRUPT_MASK_AXI_WRITE_ERROR |
205 A2XX_MH_INTERRUPT_MASK_MMU_PAGE_FAULT);
206
207 for (i = 3; i <= 5; i++)
208 if ((SZ_16K << i) == adreno_gpu->info->gmem)
209 break;
210 gpu_write(gpu, REG_A2XX_RB_EDRAM_INFO, i);
211
212 ret = adreno_hw_init(gpu);
213 if (ret)
214 return ret;
215
216 gpu_write(gpu, REG_AXXX_CP_RB_CNTL,
217 MSM_GPU_RB_CNTL_DEFAULT | AXXX_CP_RB_CNTL_NO_UPDATE);
218
219 gpu_write(gpu, REG_AXXX_CP_RB_BASE, lower_32_bits(gpu->rb[0]->iova));
220
221 /* NOTE: PM4/micro-engine firmware registers look to be the same
222 * for a2xx and a3xx.. we could possibly push that part down to
223 * adreno_gpu base class. Or push both PM4 and PFP but
224 * parameterize the pfp ucode addr/data registers..
225 */
226
227 /* Load PM4: */
228 ptr = (uint32_t *)(adreno_gpu->fw[ADRENO_FW_PM4]->data);
229 len = adreno_gpu->fw[ADRENO_FW_PM4]->size / 4;
230 DBG("loading PM4 ucode version: %x", ptr[1]);
231
232 /*
233 * New firmware files seem to have GPU and firmware version in this
234 * word (0x20xxxx for A200, 0x220xxx for A220, 0x225xxx for A225).
235 * Older firmware files, which lack protection support, have 0 instead.
236 */
237 if (ptr[1] == 0) {
238 dev_warn(gpu->dev->dev,
239 "Legacy firmware detected, disabling protection support\n");
240 a2xx_gpu->protection_disabled = true;
241 }
242
243 gpu_write(gpu, REG_AXXX_CP_DEBUG,
244 AXXX_CP_DEBUG_MIU_128BIT_WRITE_ENABLE);
245 gpu_write(gpu, REG_AXXX_CP_ME_RAM_WADDR, 0);
246 for (i = 1; i < len; i++)
247 gpu_write(gpu, REG_AXXX_CP_ME_RAM_DATA, ptr[i]);
248
249 /* Load PFP: */
250 ptr = (uint32_t *)(adreno_gpu->fw[ADRENO_FW_PFP]->data);
251 len = adreno_gpu->fw[ADRENO_FW_PFP]->size / 4;
252 DBG("loading PFP ucode version: %x", ptr[5]);
253
254 gpu_write(gpu, REG_A2XX_CP_PFP_UCODE_ADDR, 0);
255 for (i = 1; i < len; i++)
256 gpu_write(gpu, REG_A2XX_CP_PFP_UCODE_DATA, ptr[i]);
257
258 gpu_write(gpu, REG_AXXX_CP_QUEUE_THRESHOLDS, 0x000C0804);
259
260 /* clear ME_HALT to start micro engine */
261 gpu_write(gpu, REG_AXXX_CP_ME_CNTL, 0);
262
263 return a2xx_me_init(gpu) ? 0 : -EINVAL;
264}
265
266static void a2xx_recover(struct msm_gpu *gpu)
267{
268 int i;
269
270 adreno_dump_info(gpu);
271
272 for (i = 0; i < 8; i++) {
273 printk("CP_SCRATCH_REG%d: %u\n", i,
274 gpu_read(gpu, REG_AXXX_CP_SCRATCH_REG0 + i));
275 }
276
277 /* dump registers before resetting gpu, if enabled: */
278 if (hang_debug)
279 a2xx_dump(gpu);
280
281 gpu_write(gpu, REG_A2XX_RBBM_SOFT_RESET, 1);
282 gpu_read(gpu, REG_A2XX_RBBM_SOFT_RESET);
283 gpu_write(gpu, REG_A2XX_RBBM_SOFT_RESET, 0);
284 adreno_recover(gpu);
285}
286
287static void a2xx_destroy(struct msm_gpu *gpu)
288{
289 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
290 struct a2xx_gpu *a2xx_gpu = to_a2xx_gpu(adreno_gpu);
291
292 DBG("%s", gpu->name);
293
294 adreno_gpu_cleanup(gpu: adreno_gpu);
295
296 kfree(a2xx_gpu);
297}
298
299static bool a2xx_idle(struct msm_gpu *gpu)
300{
301 /* wait for ringbuffer to drain: */
302 if (!adreno_idle(gpu, ring: gpu->rb[0]))
303 return false;
304
305 /* then wait for GPU to finish: */
306 if (spin_until(!(gpu_read(gpu, REG_A2XX_RBBM_STATUS) &
307 A2XX_RBBM_STATUS_GUI_ACTIVE))) {
308 DRM_ERROR("%s: timeout waiting for GPU to idle!\n", gpu->name);
309
310 /* TODO maybe we need to reset GPU here to recover from hang? */
311 return false;
312 }
313
314 return true;
315}
316
317static irqreturn_t a2xx_irq(struct msm_gpu *gpu)
318{
319 uint32_t mstatus, status;
320
321 mstatus = gpu_read(gpu, REG_A2XX_MASTER_INT_SIGNAL);
322
323 if (mstatus & A2XX_MASTER_INT_SIGNAL_MH_INT_STAT) {
324 status = gpu_read(gpu, REG_A2XX_MH_INTERRUPT_STATUS);
325
326 dev_warn(gpu->dev->dev, "MH_INT: %08X\n", status);
327 dev_warn(gpu->dev->dev, "MMU_PAGE_FAULT: %08X\n",
328 gpu_read(gpu, REG_A2XX_MH_MMU_PAGE_FAULT));
329
330 gpu_write(gpu, REG_A2XX_MH_INTERRUPT_CLEAR, status);
331 }
332
333 if (mstatus & A2XX_MASTER_INT_SIGNAL_CP_INT_STAT) {
334 status = gpu_read(gpu, REG_AXXX_CP_INT_STATUS);
335
336 /* only RB_INT is expected */
337 if (status & ~AXXX_CP_INT_CNTL_RB_INT_MASK)
338 dev_warn(gpu->dev->dev, "CP_INT: %08X\n", status);
339
340 gpu_write(gpu, REG_AXXX_CP_INT_ACK, status);
341 }
342
343 if (mstatus & A2XX_MASTER_INT_SIGNAL_RBBM_INT_STAT) {
344 status = gpu_read(gpu, REG_A2XX_RBBM_INT_STATUS);
345
346 dev_warn(gpu->dev->dev, "RBBM_INT: %08X\n", status);
347
348 gpu_write(gpu, REG_A2XX_RBBM_INT_ACK, status);
349 }
350
351 msm_gpu_retire(gpu);
352
353 return IRQ_HANDLED;
354}
355
356static const unsigned int a200_registers[] = {
357 0x0000, 0x0002, 0x0004, 0x000B, 0x003B, 0x003D, 0x0040, 0x0044,
358 0x0046, 0x0047, 0x01C0, 0x01C1, 0x01C3, 0x01C8, 0x01D5, 0x01D9,
359 0x01DC, 0x01DD, 0x01EA, 0x01EA, 0x01EE, 0x01F3, 0x01F6, 0x01F7,
360 0x01FC, 0x01FF, 0x0391, 0x0392, 0x039B, 0x039E, 0x03B2, 0x03B5,
361 0x03B7, 0x03B7, 0x03F8, 0x03FB, 0x0440, 0x0440, 0x0443, 0x0444,
362 0x044B, 0x044B, 0x044D, 0x044F, 0x0452, 0x0452, 0x0454, 0x045B,
363 0x047F, 0x047F, 0x0578, 0x0587, 0x05C9, 0x05C9, 0x05D0, 0x05D0,
364 0x0601, 0x0604, 0x0606, 0x0609, 0x060B, 0x060E, 0x0613, 0x0614,
365 0x0A29, 0x0A2B, 0x0A2F, 0x0A31, 0x0A40, 0x0A43, 0x0A45, 0x0A45,
366 0x0A4E, 0x0A4F, 0x0C2C, 0x0C2C, 0x0C30, 0x0C30, 0x0C38, 0x0C3C,
367 0x0C40, 0x0C40, 0x0C44, 0x0C44, 0x0C80, 0x0C86, 0x0C88, 0x0C94,
368 0x0C99, 0x0C9A, 0x0CA4, 0x0CA5, 0x0D00, 0x0D03, 0x0D06, 0x0D06,
369 0x0D08, 0x0D0B, 0x0D34, 0x0D35, 0x0DAE, 0x0DC1, 0x0DC8, 0x0DD4,
370 0x0DD8, 0x0DD9, 0x0E00, 0x0E00, 0x0E02, 0x0E04, 0x0E17, 0x0E1E,
371 0x0EC0, 0x0EC9, 0x0ECB, 0x0ECC, 0x0ED0, 0x0ED0, 0x0ED4, 0x0ED7,
372 0x0EE0, 0x0EE2, 0x0F01, 0x0F02, 0x0F0C, 0x0F0C, 0x0F0E, 0x0F12,
373 0x0F26, 0x0F2A, 0x0F2C, 0x0F2C, 0x2000, 0x2002, 0x2006, 0x200F,
374 0x2080, 0x2082, 0x2100, 0x2109, 0x210C, 0x2114, 0x2180, 0x2184,
375 0x21F5, 0x21F7, 0x2200, 0x2208, 0x2280, 0x2283, 0x2293, 0x2294,
376 0x2300, 0x2308, 0x2312, 0x2312, 0x2316, 0x231D, 0x2324, 0x2326,
377 0x2380, 0x2383, 0x2400, 0x2402, 0x2406, 0x240F, 0x2480, 0x2482,
378 0x2500, 0x2509, 0x250C, 0x2514, 0x2580, 0x2584, 0x25F5, 0x25F7,
379 0x2600, 0x2608, 0x2680, 0x2683, 0x2693, 0x2694, 0x2700, 0x2708,
380 0x2712, 0x2712, 0x2716, 0x271D, 0x2724, 0x2726, 0x2780, 0x2783,
381 0x4000, 0x4003, 0x4800, 0x4805, 0x4900, 0x4900, 0x4908, 0x4908,
382 ~0 /* sentinel */
383};
384
385static const unsigned int a220_registers[] = {
386 0x0000, 0x0002, 0x0004, 0x000B, 0x003B, 0x003D, 0x0040, 0x0044,
387 0x0046, 0x0047, 0x01C0, 0x01C1, 0x01C3, 0x01C8, 0x01D5, 0x01D9,
388 0x01DC, 0x01DD, 0x01EA, 0x01EA, 0x01EE, 0x01F3, 0x01F6, 0x01F7,
389 0x01FC, 0x01FF, 0x0391, 0x0392, 0x039B, 0x039E, 0x03B2, 0x03B5,
390 0x03B7, 0x03B7, 0x03F8, 0x03FB, 0x0440, 0x0440, 0x0443, 0x0444,
391 0x044B, 0x044B, 0x044D, 0x044F, 0x0452, 0x0452, 0x0454, 0x045B,
392 0x047F, 0x047F, 0x0578, 0x0587, 0x05C9, 0x05C9, 0x05D0, 0x05D0,
393 0x0601, 0x0604, 0x0606, 0x0609, 0x060B, 0x060E, 0x0613, 0x0614,
394 0x0A29, 0x0A2B, 0x0A2F, 0x0A31, 0x0A40, 0x0A40, 0x0A42, 0x0A43,
395 0x0A45, 0x0A45, 0x0A4E, 0x0A4F, 0x0C30, 0x0C30, 0x0C38, 0x0C39,
396 0x0C3C, 0x0C3C, 0x0C80, 0x0C81, 0x0C88, 0x0C93, 0x0D00, 0x0D03,
397 0x0D05, 0x0D06, 0x0D08, 0x0D0B, 0x0D34, 0x0D35, 0x0DAE, 0x0DC1,
398 0x0DC8, 0x0DD4, 0x0DD8, 0x0DD9, 0x0E00, 0x0E00, 0x0E02, 0x0E04,
399 0x0E17, 0x0E1E, 0x0EC0, 0x0EC9, 0x0ECB, 0x0ECC, 0x0ED0, 0x0ED0,
400 0x0ED4, 0x0ED7, 0x0EE0, 0x0EE2, 0x0F01, 0x0F02, 0x2000, 0x2002,
401 0x2006, 0x200F, 0x2080, 0x2082, 0x2100, 0x2102, 0x2104, 0x2109,
402 0x210C, 0x2114, 0x2180, 0x2184, 0x21F5, 0x21F7, 0x2200, 0x2202,
403 0x2204, 0x2204, 0x2208, 0x2208, 0x2280, 0x2282, 0x2294, 0x2294,
404 0x2300, 0x2308, 0x2309, 0x230A, 0x2312, 0x2312, 0x2316, 0x2316,
405 0x2318, 0x231D, 0x2324, 0x2326, 0x2380, 0x2383, 0x2400, 0x2402,
406 0x2406, 0x240F, 0x2480, 0x2482, 0x2500, 0x2502, 0x2504, 0x2509,
407 0x250C, 0x2514, 0x2580, 0x2584, 0x25F5, 0x25F7, 0x2600, 0x2602,
408 0x2604, 0x2606, 0x2608, 0x2608, 0x2680, 0x2682, 0x2694, 0x2694,
409 0x2700, 0x2708, 0x2712, 0x2712, 0x2716, 0x2716, 0x2718, 0x271D,
410 0x2724, 0x2726, 0x2780, 0x2783, 0x4000, 0x4003, 0x4800, 0x4805,
411 0x4900, 0x4900, 0x4908, 0x4908,
412 ~0 /* sentinel */
413};
414
415static const unsigned int a225_registers[] = {
416 0x0000, 0x0002, 0x0004, 0x000B, 0x003B, 0x003D, 0x0040, 0x0044,
417 0x0046, 0x0047, 0x013C, 0x013C, 0x0140, 0x014F, 0x01C0, 0x01C1,
418 0x01C3, 0x01C8, 0x01D5, 0x01D9, 0x01DC, 0x01DD, 0x01EA, 0x01EA,
419 0x01EE, 0x01F3, 0x01F6, 0x01F7, 0x01FC, 0x01FF, 0x0391, 0x0392,
420 0x039B, 0x039E, 0x03B2, 0x03B5, 0x03B7, 0x03B7, 0x03F8, 0x03FB,
421 0x0440, 0x0440, 0x0443, 0x0444, 0x044B, 0x044B, 0x044D, 0x044F,
422 0x0452, 0x0452, 0x0454, 0x045B, 0x047F, 0x047F, 0x0578, 0x0587,
423 0x05C9, 0x05C9, 0x05D0, 0x05D0, 0x0601, 0x0604, 0x0606, 0x0609,
424 0x060B, 0x060E, 0x0613, 0x0614, 0x0A29, 0x0A2B, 0x0A2F, 0x0A31,
425 0x0A40, 0x0A40, 0x0A42, 0x0A43, 0x0A45, 0x0A45, 0x0A4E, 0x0A4F,
426 0x0C01, 0x0C1D, 0x0C30, 0x0C30, 0x0C38, 0x0C39, 0x0C3C, 0x0C3C,
427 0x0C80, 0x0C81, 0x0C88, 0x0C93, 0x0D00, 0x0D03, 0x0D05, 0x0D06,
428 0x0D08, 0x0D0B, 0x0D34, 0x0D35, 0x0DAE, 0x0DC1, 0x0DC8, 0x0DD4,
429 0x0DD8, 0x0DD9, 0x0E00, 0x0E00, 0x0E02, 0x0E04, 0x0E17, 0x0E1E,
430 0x0EC0, 0x0EC9, 0x0ECB, 0x0ECC, 0x0ED0, 0x0ED0, 0x0ED4, 0x0ED7,
431 0x0EE0, 0x0EE2, 0x0F01, 0x0F02, 0x2000, 0x200F, 0x2080, 0x2082,
432 0x2100, 0x2109, 0x210C, 0x2114, 0x2180, 0x2184, 0x21F5, 0x21F7,
433 0x2200, 0x2202, 0x2204, 0x2206, 0x2208, 0x2210, 0x2220, 0x2222,
434 0x2280, 0x2282, 0x2294, 0x2294, 0x2297, 0x2297, 0x2300, 0x230A,
435 0x2312, 0x2312, 0x2315, 0x2316, 0x2318, 0x231D, 0x2324, 0x2326,
436 0x2340, 0x2357, 0x2360, 0x2360, 0x2380, 0x2383, 0x2400, 0x240F,
437 0x2480, 0x2482, 0x2500, 0x2509, 0x250C, 0x2514, 0x2580, 0x2584,
438 0x25F5, 0x25F7, 0x2600, 0x2602, 0x2604, 0x2606, 0x2608, 0x2610,
439 0x2620, 0x2622, 0x2680, 0x2682, 0x2694, 0x2694, 0x2697, 0x2697,
440 0x2700, 0x270A, 0x2712, 0x2712, 0x2715, 0x2716, 0x2718, 0x271D,
441 0x2724, 0x2726, 0x2740, 0x2757, 0x2760, 0x2760, 0x2780, 0x2783,
442 0x4000, 0x4003, 0x4800, 0x4806, 0x4808, 0x4808, 0x4900, 0x4900,
443 0x4908, 0x4908,
444 ~0 /* sentinel */
445};
446
447/* would be nice to not have to duplicate the _show() stuff with printk(): */
448static void a2xx_dump(struct msm_gpu *gpu)
449{
450 printk("status: %08x\n",
451 gpu_read(gpu, REG_A2XX_RBBM_STATUS));
452 adreno_dump(gpu);
453}
454
455static struct msm_gpu_state *a2xx_gpu_state_get(struct msm_gpu *gpu)
456{
457 struct msm_gpu_state *state = kzalloc(sizeof(*state), GFP_KERNEL);
458
459 if (!state)
460 return ERR_PTR(error: -ENOMEM);
461
462 adreno_gpu_state_get(gpu, state);
463
464 state->rbbm_status = gpu_read(gpu, REG_A2XX_RBBM_STATUS);
465
466 return state;
467}
468
469static struct msm_gem_address_space *
470a2xx_create_address_space(struct msm_gpu *gpu, struct platform_device *pdev)
471{
472 struct msm_mmu *mmu = msm_gpummu_new(&pdev->dev, gpu);
473 struct msm_gem_address_space *aspace;
474
475 aspace = msm_gem_address_space_create(mmu, "gpu", SZ_16M,
476 0xfff * SZ_64K);
477
478 if (IS_ERR(ptr: aspace) && !IS_ERR(ptr: mmu))
479 mmu->funcs->destroy(mmu);
480
481 return aspace;
482}
483
484static u32 a2xx_get_rptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
485{
486 ring->memptrs->rptr = gpu_read(gpu, REG_AXXX_CP_RB_RPTR);
487 return ring->memptrs->rptr;
488}
489
490static const struct adreno_gpu_funcs funcs = {
491 .base = {
492 .get_param = adreno_get_param,
493 .set_param = adreno_set_param,
494 .hw_init = a2xx_hw_init,
495 .pm_suspend = msm_gpu_pm_suspend,
496 .pm_resume = msm_gpu_pm_resume,
497 .recover = a2xx_recover,
498 .submit = a2xx_submit,
499 .active_ring = adreno_active_ring,
500 .irq = a2xx_irq,
501 .destroy = a2xx_destroy,
502#if defined(CONFIG_DEBUG_FS) || defined(CONFIG_DEV_COREDUMP)
503 .show = adreno_show,
504#endif
505 .gpu_state_get = a2xx_gpu_state_get,
506 .gpu_state_put = adreno_gpu_state_put,
507 .create_address_space = a2xx_create_address_space,
508 .get_rptr = a2xx_get_rptr,
509 },
510};
511
512static const struct msm_gpu_perfcntr perfcntrs[] = {
513/* TODO */
514};
515
516struct msm_gpu *a2xx_gpu_init(struct drm_device *dev)
517{
518 struct a2xx_gpu *a2xx_gpu = NULL;
519 struct adreno_gpu *adreno_gpu;
520 struct msm_gpu *gpu;
521 struct msm_drm_private *priv = dev->dev_private;
522 struct platform_device *pdev = priv->gpu_pdev;
523 int ret;
524
525 if (!pdev) {
526 dev_err(dev->dev, "no a2xx device\n");
527 ret = -ENXIO;
528 goto fail;
529 }
530
531 a2xx_gpu = kzalloc(sizeof(*a2xx_gpu), GFP_KERNEL);
532 if (!a2xx_gpu) {
533 ret = -ENOMEM;
534 goto fail;
535 }
536
537 adreno_gpu = &a2xx_gpu->base;
538 gpu = &adreno_gpu->base;
539
540 gpu->perfcntrs = perfcntrs;
541 gpu->num_perfcntrs = ARRAY_SIZE(perfcntrs);
542
543 ret = adreno_gpu_init(drm: dev, pdev, gpu: adreno_gpu, funcs: &funcs, nr_rings: 1);
544 if (ret)
545 goto fail;
546
547 if (adreno_is_a20x(gpu: adreno_gpu))
548 adreno_gpu->registers = a200_registers;
549 else if (adreno_is_a225(gpu: adreno_gpu))
550 adreno_gpu->registers = a225_registers;
551 else
552 adreno_gpu->registers = a220_registers;
553
554 if (!gpu->aspace) {
555 dev_err(dev->dev, "No memory protection without MMU\n");
556 if (!allow_vram_carveout) {
557 ret = -ENXIO;
558 goto fail;
559 }
560 }
561
562 return gpu;
563
564fail:
565 if (a2xx_gpu)
566 a2xx_destroy(gpu: &a2xx_gpu->base.base);
567
568 return ERR_PTR(error: ret);
569}
570

source code of linux/drivers/gpu/drm/msm/adreno/a2xx_gpu.c