2 * Copyright (C) 2013 Red Hat
3 * Author: Rob Clark <robdclark@gmail.com>
5 * Copyright (c) 2014 The Linux Foundation. All rights reserved.
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License version 2 as published by
9 * the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * You should have received a copy of the GNU General Public License along with
17 * this program. If not, see <http://www.gnu.org/licenses/>.
20 #ifdef CONFIG_MSM_OCMEM
21 # include <mach/ocmem.h>
26 #define A3XX_INT0_MASK \
27 (A3XX_INT0_RBBM_AHB_ERROR | \
28 A3XX_INT0_RBBM_ATB_BUS_OVERFLOW | \
29 A3XX_INT0_CP_T0_PACKET_IN_IB | \
30 A3XX_INT0_CP_OPCODE_ERROR | \
31 A3XX_INT0_CP_RESERVED_BIT_ERROR | \
32 A3XX_INT0_CP_HW_FAULT | \
33 A3XX_INT0_CP_IB1_INT | \
34 A3XX_INT0_CP_IB2_INT | \
35 A3XX_INT0_CP_RB_INT | \
36 A3XX_INT0_CP_REG_PROTECT_FAULT | \
37 A3XX_INT0_CP_AHB_ERROR_HALT | \
38 A3XX_INT0_UCHE_OOB_ACCESS)
40 extern bool hang_debug;
42 static void a3xx_dump(struct msm_gpu *gpu);
43 static bool a3xx_idle(struct msm_gpu *gpu);
45 static bool a3xx_me_init(struct msm_gpu *gpu)
47 struct msm_ringbuffer *ring = gpu->rb;
49 OUT_PKT3(ring, CP_ME_INIT, 17);
50 OUT_RING(ring, 0x000003f7);
51 OUT_RING(ring, 0x00000000);
52 OUT_RING(ring, 0x00000000);
53 OUT_RING(ring, 0x00000000);
54 OUT_RING(ring, 0x00000080);
55 OUT_RING(ring, 0x00000100);
56 OUT_RING(ring, 0x00000180);
57 OUT_RING(ring, 0x00006600);
58 OUT_RING(ring, 0x00000150);
59 OUT_RING(ring, 0x0000014e);
60 OUT_RING(ring, 0x00000154);
61 OUT_RING(ring, 0x00000001);
62 OUT_RING(ring, 0x00000000);
63 OUT_RING(ring, 0x00000000);
64 OUT_RING(ring, 0x00000000);
65 OUT_RING(ring, 0x00000000);
66 OUT_RING(ring, 0x00000000);
68 gpu->funcs->flush(gpu);
69 return a3xx_idle(gpu);
72 static int a3xx_hw_init(struct msm_gpu *gpu)
74 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
75 struct a3xx_gpu *a3xx_gpu = to_a3xx_gpu(adreno_gpu);
81 if (adreno_is_a305(adreno_gpu)) {
82 /* Set up 16 deep read/write request queues: */
83 gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF0, 0x10101010);
84 gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF1, 0x10101010);
85 gpu_write(gpu, REG_A3XX_VBIF_OUT_RD_LIM_CONF0, 0x10101010);
86 gpu_write(gpu, REG_A3XX_VBIF_OUT_WR_LIM_CONF0, 0x10101010);
87 gpu_write(gpu, REG_A3XX_VBIF_DDR_OUT_MAX_BURST, 0x0000303);
88 gpu_write(gpu, REG_A3XX_VBIF_IN_WR_LIM_CONF0, 0x10101010);
89 gpu_write(gpu, REG_A3XX_VBIF_IN_WR_LIM_CONF1, 0x10101010);
91 gpu_write(gpu, REG_A3XX_VBIF_GATE_OFF_WRREQ_EN, 0x0000ff);
92 /* Set up round robin arbitration between both AXI ports: */
93 gpu_write(gpu, REG_A3XX_VBIF_ARB_CTL, 0x00000030);
95 gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO_EN, 0x0000003c);
96 gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO, 0x003c003c);
97 } else if (adreno_is_a306(adreno_gpu)) {
98 gpu_write(gpu, REG_A3XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x0003);
99 gpu_write(gpu, REG_A3XX_VBIF_OUT_RD_LIM_CONF0, 0x0000000a);
100 gpu_write(gpu, REG_A3XX_VBIF_OUT_WR_LIM_CONF0, 0x0000000a);
101 } else if (adreno_is_a320(adreno_gpu)) {
102 /* Set up 16 deep read/write request queues: */
103 gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF0, 0x10101010);
104 gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF1, 0x10101010);
105 gpu_write(gpu, REG_A3XX_VBIF_OUT_RD_LIM_CONF0, 0x10101010);
106 gpu_write(gpu, REG_A3XX_VBIF_OUT_WR_LIM_CONF0, 0x10101010);
107 gpu_write(gpu, REG_A3XX_VBIF_DDR_OUT_MAX_BURST, 0x0000303);
108 gpu_write(gpu, REG_A3XX_VBIF_IN_WR_LIM_CONF0, 0x10101010);
109 gpu_write(gpu, REG_A3XX_VBIF_IN_WR_LIM_CONF1, 0x10101010);
111 gpu_write(gpu, REG_A3XX_VBIF_GATE_OFF_WRREQ_EN, 0x0000ff);
112 /* Set up round robin arbitration between both AXI ports: */
113 gpu_write(gpu, REG_A3XX_VBIF_ARB_CTL, 0x00000030);
115 gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO_EN, 0x0000003c);
116 gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO, 0x003c003c);
117 /* Enable 1K sort: */
118 gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT, 0x000000ff);
119 gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT_CONF, 0x000000a4);
121 } else if (adreno_is_a330v2(adreno_gpu)) {
123 * Most of the VBIF registers on 8974v2 have the correct
124 * values at power on, so we won't modify those if we don't
127 /* Enable 1k sort: */
128 gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT, 0x0001003f);
129 gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT_CONF, 0x000000a4);
131 gpu_write(gpu, REG_A3XX_VBIF_GATE_OFF_WRREQ_EN, 0x00003f);
132 gpu_write(gpu, REG_A3XX_VBIF_DDR_OUT_MAX_BURST, 0x0000303);
133 /* Set up VBIF_ROUND_ROBIN_QOS_ARB: */
134 gpu_write(gpu, REG_A3XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x0003);
136 } else if (adreno_is_a330(adreno_gpu)) {
137 /* Set up 16 deep read/write request queues: */
138 gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF0, 0x18181818);
139 gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF1, 0x18181818);
140 gpu_write(gpu, REG_A3XX_VBIF_OUT_RD_LIM_CONF0, 0x18181818);
141 gpu_write(gpu, REG_A3XX_VBIF_OUT_WR_LIM_CONF0, 0x18181818);
142 gpu_write(gpu, REG_A3XX_VBIF_DDR_OUT_MAX_BURST, 0x0000303);
143 gpu_write(gpu, REG_A3XX_VBIF_IN_WR_LIM_CONF0, 0x18181818);
144 gpu_write(gpu, REG_A3XX_VBIF_IN_WR_LIM_CONF1, 0x18181818);
146 gpu_write(gpu, REG_A3XX_VBIF_GATE_OFF_WRREQ_EN, 0x00003f);
147 /* Set up round robin arbitration between both AXI ports: */
148 gpu_write(gpu, REG_A3XX_VBIF_ARB_CTL, 0x00000030);
149 /* Set up VBIF_ROUND_ROBIN_QOS_ARB: */
150 gpu_write(gpu, REG_A3XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x0001);
152 gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO_EN, 0x0000003f);
153 gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO, 0x003f003f);
154 /* Enable 1K sort: */
155 gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT, 0x0001003f);
156 gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT_CONF, 0x000000a4);
157 /* Disable VBIF clock gating. This is to enable AXI running
158 * higher frequency than GPU:
160 gpu_write(gpu, REG_A3XX_VBIF_CLKON, 0x00000001);
166 /* Make all blocks contribute to the GPU BUSY perf counter: */
167 gpu_write(gpu, REG_A3XX_RBBM_GPU_BUSY_MASKED, 0xffffffff);
169 /* Tune the hystersis counters for SP and CP idle detection: */
170 gpu_write(gpu, REG_A3XX_RBBM_SP_HYST_CNT, 0x10);
171 gpu_write(gpu, REG_A3XX_RBBM_WAIT_IDLE_CLOCKS_CTL, 0x10);
173 /* Enable the RBBM error reporting bits. This lets us get
174 * useful information on failure:
176 gpu_write(gpu, REG_A3XX_RBBM_AHB_CTL0, 0x00000001);
178 /* Enable AHB error reporting: */
179 gpu_write(gpu, REG_A3XX_RBBM_AHB_CTL1, 0xa6ffffff);
181 /* Turn on the power counters: */
182 gpu_write(gpu, REG_A3XX_RBBM_RBBM_CTL, 0x00030000);
184 /* Turn on hang detection - this spews a lot of useful information
185 * into the RBBM registers on a hang:
187 gpu_write(gpu, REG_A3XX_RBBM_INTERFACE_HANG_INT_CTL, 0x00010fff);
189 /* Enable 64-byte cacheline size. HW Default is 32-byte (0x000000E0): */
190 gpu_write(gpu, REG_A3XX_UCHE_CACHE_MODE_CONTROL_REG, 0x00000001);
192 /* Enable Clock gating: */
193 if (adreno_is_a306(adreno_gpu))
194 gpu_write(gpu, REG_A3XX_RBBM_CLOCK_CTL, 0xaaaaaaaa);
195 else if (adreno_is_a320(adreno_gpu))
196 gpu_write(gpu, REG_A3XX_RBBM_CLOCK_CTL, 0xbfffffff);
197 else if (adreno_is_a330v2(adreno_gpu))
198 gpu_write(gpu, REG_A3XX_RBBM_CLOCK_CTL, 0xaaaaaaaa);
199 else if (adreno_is_a330(adreno_gpu))
200 gpu_write(gpu, REG_A3XX_RBBM_CLOCK_CTL, 0xbffcffff);
202 if (adreno_is_a330v2(adreno_gpu))
203 gpu_write(gpu, REG_A3XX_RBBM_GPR0_CTL, 0x05515455);
204 else if (adreno_is_a330(adreno_gpu))
205 gpu_write(gpu, REG_A3XX_RBBM_GPR0_CTL, 0x00000000);
207 /* Set the OCMEM base address for A330, etc */
208 if (a3xx_gpu->ocmem_hdl) {
209 gpu_write(gpu, REG_A3XX_RB_GMEM_BASE_ADDR,
210 (unsigned int)(a3xx_gpu->ocmem_base >> 14));
213 /* Turn on performance counters: */
214 gpu_write(gpu, REG_A3XX_RBBM_PERFCTR_CTL, 0x01);
216 /* Enable the perfcntrs that we use.. */
217 for (i = 0; i < gpu->num_perfcntrs; i++) {
218 const struct msm_gpu_perfcntr *perfcntr = &gpu->perfcntrs[i];
219 gpu_write(gpu, perfcntr->select_reg, perfcntr->select_val);
222 gpu_write(gpu, REG_A3XX_RBBM_INT_0_MASK, A3XX_INT0_MASK);
224 ret = adreno_hw_init(gpu);
228 /* setup access protection: */
229 gpu_write(gpu, REG_A3XX_CP_PROTECT_CTRL, 0x00000007);
232 gpu_write(gpu, REG_A3XX_CP_PROTECT(0), 0x63000040);
233 gpu_write(gpu, REG_A3XX_CP_PROTECT(1), 0x62000080);
234 gpu_write(gpu, REG_A3XX_CP_PROTECT(2), 0x600000cc);
235 gpu_write(gpu, REG_A3XX_CP_PROTECT(3), 0x60000108);
236 gpu_write(gpu, REG_A3XX_CP_PROTECT(4), 0x64000140);
237 gpu_write(gpu, REG_A3XX_CP_PROTECT(5), 0x66000400);
240 gpu_write(gpu, REG_A3XX_CP_PROTECT(6), 0x65000700);
241 gpu_write(gpu, REG_A3XX_CP_PROTECT(7), 0x610007d8);
242 gpu_write(gpu, REG_A3XX_CP_PROTECT(8), 0x620007e0);
243 gpu_write(gpu, REG_A3XX_CP_PROTECT(9), 0x61001178);
244 gpu_write(gpu, REG_A3XX_CP_PROTECT(10), 0x64001180);
247 gpu_write(gpu, REG_A3XX_CP_PROTECT(11), 0x60003300);
250 gpu_write(gpu, REG_A3XX_CP_PROTECT(12), 0x6b00c000);
252 /* NOTE: PM4/micro-engine firmware registers look to be the same
253 * for a2xx and a3xx.. we could possibly push that part down to
254 * adreno_gpu base class. Or push both PM4 and PFP but
255 * parameterize the pfp ucode addr/data registers..
259 ptr = (uint32_t *)(adreno_gpu->pm4->data);
260 len = adreno_gpu->pm4->size / 4;
261 DBG("loading PM4 ucode version: %x", ptr[1]);
263 gpu_write(gpu, REG_AXXX_CP_DEBUG,
264 AXXX_CP_DEBUG_DYNAMIC_CLK_DISABLE |
265 AXXX_CP_DEBUG_MIU_128BIT_WRITE_ENABLE);
266 gpu_write(gpu, REG_AXXX_CP_ME_RAM_WADDR, 0);
267 for (i = 1; i < len; i++)
268 gpu_write(gpu, REG_AXXX_CP_ME_RAM_DATA, ptr[i]);
271 ptr = (uint32_t *)(adreno_gpu->pfp->data);
272 len = adreno_gpu->pfp->size / 4;
273 DBG("loading PFP ucode version: %x", ptr[5]);
275 gpu_write(gpu, REG_A3XX_CP_PFP_UCODE_ADDR, 0);
276 for (i = 1; i < len; i++)
277 gpu_write(gpu, REG_A3XX_CP_PFP_UCODE_DATA, ptr[i]);
279 /* CP ROQ queue sizes (bytes) - RB:16, ST:16, IB1:32, IB2:64 */
280 if (adreno_is_a305(adreno_gpu) || adreno_is_a306(adreno_gpu) ||
281 adreno_is_a320(adreno_gpu)) {
282 gpu_write(gpu, REG_AXXX_CP_QUEUE_THRESHOLDS,
283 AXXX_CP_QUEUE_THRESHOLDS_CSQ_IB1_START(2) |
284 AXXX_CP_QUEUE_THRESHOLDS_CSQ_IB2_START(6) |
285 AXXX_CP_QUEUE_THRESHOLDS_CSQ_ST_START(14));
286 } else if (adreno_is_a330(adreno_gpu)) {
287 /* NOTE: this (value take from downstream android driver)
288 * includes some bits outside of the known bitfields. But
289 * A330 has this "MERCIU queue" thing too, which might
290 * explain a new bitfield or reshuffling:
292 gpu_write(gpu, REG_AXXX_CP_QUEUE_THRESHOLDS, 0x003e2008);
295 /* clear ME_HALT to start micro engine */
296 gpu_write(gpu, REG_AXXX_CP_ME_CNTL, 0);
298 return a3xx_me_init(gpu) ? 0 : -EINVAL;
301 static void a3xx_recover(struct msm_gpu *gpu)
305 adreno_dump_info(gpu);
307 for (i = 0; i < 8; i++) {
308 printk("CP_SCRATCH_REG%d: %u\n", i,
309 gpu_read(gpu, REG_AXXX_CP_SCRATCH_REG0 + i));
312 /* dump registers before resetting gpu, if enabled: */
316 gpu_write(gpu, REG_A3XX_RBBM_SW_RESET_CMD, 1);
317 gpu_read(gpu, REG_A3XX_RBBM_SW_RESET_CMD);
318 gpu_write(gpu, REG_A3XX_RBBM_SW_RESET_CMD, 0);
322 static void a3xx_destroy(struct msm_gpu *gpu)
324 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
325 struct a3xx_gpu *a3xx_gpu = to_a3xx_gpu(adreno_gpu);
327 DBG("%s", gpu->name);
329 adreno_gpu_cleanup(adreno_gpu);
331 #ifdef CONFIG_MSM_OCMEM
332 if (a3xx_gpu->ocmem_base)
333 ocmem_free(OCMEM_GRAPHICS, a3xx_gpu->ocmem_hdl);
339 static bool a3xx_idle(struct msm_gpu *gpu)
341 /* wait for ringbuffer to drain: */
342 if (!adreno_idle(gpu))
345 /* then wait for GPU to finish: */
346 if (spin_until(!(gpu_read(gpu, REG_A3XX_RBBM_STATUS) &
347 A3XX_RBBM_STATUS_GPU_BUSY))) {
348 DRM_ERROR("%s: timeout waiting for GPU to idle!\n", gpu->name);
350 /* TODO maybe we need to reset GPU here to recover from hang? */
357 static irqreturn_t a3xx_irq(struct msm_gpu *gpu)
361 status = gpu_read(gpu, REG_A3XX_RBBM_INT_0_STATUS);
362 DBG("%s: %08x", gpu->name, status);
366 gpu_write(gpu, REG_A3XX_RBBM_INT_CLEAR_CMD, status);
373 static const unsigned int a3xx_registers[] = {
374 0x0000, 0x0002, 0x0010, 0x0012, 0x0018, 0x0018, 0x0020, 0x0027,
375 0x0029, 0x002b, 0x002e, 0x0033, 0x0040, 0x0042, 0x0050, 0x005c,
376 0x0060, 0x006c, 0x0080, 0x0082, 0x0084, 0x0088, 0x0090, 0x00e5,
377 0x00ea, 0x00ed, 0x0100, 0x0100, 0x0110, 0x0123, 0x01c0, 0x01c1,
378 0x01c3, 0x01c5, 0x01c7, 0x01c7, 0x01d5, 0x01d9, 0x01dc, 0x01dd,
379 0x01ea, 0x01ea, 0x01ee, 0x01f1, 0x01f5, 0x01f5, 0x01fc, 0x01ff,
380 0x0440, 0x0440, 0x0443, 0x0443, 0x0445, 0x0445, 0x044d, 0x044f,
381 0x0452, 0x0452, 0x0454, 0x046f, 0x047c, 0x047c, 0x047f, 0x047f,
382 0x0578, 0x057f, 0x0600, 0x0602, 0x0605, 0x0607, 0x060a, 0x060e,
383 0x0612, 0x0614, 0x0c01, 0x0c02, 0x0c06, 0x0c1d, 0x0c3d, 0x0c3f,
384 0x0c48, 0x0c4b, 0x0c80, 0x0c80, 0x0c88, 0x0c8b, 0x0ca0, 0x0cb7,
385 0x0cc0, 0x0cc1, 0x0cc6, 0x0cc7, 0x0ce4, 0x0ce5, 0x0e00, 0x0e05,
386 0x0e0c, 0x0e0c, 0x0e22, 0x0e23, 0x0e41, 0x0e45, 0x0e64, 0x0e65,
387 0x0e80, 0x0e82, 0x0e84, 0x0e89, 0x0ea0, 0x0ea1, 0x0ea4, 0x0ea7,
388 0x0ec4, 0x0ecb, 0x0ee0, 0x0ee0, 0x0f00, 0x0f01, 0x0f03, 0x0f09,
389 0x2040, 0x2040, 0x2044, 0x2044, 0x2048, 0x204d, 0x2068, 0x2069,
390 0x206c, 0x206d, 0x2070, 0x2070, 0x2072, 0x2072, 0x2074, 0x2075,
391 0x2079, 0x207a, 0x20c0, 0x20d3, 0x20e4, 0x20ef, 0x2100, 0x2109,
392 0x210c, 0x210c, 0x210e, 0x210e, 0x2110, 0x2111, 0x2114, 0x2115,
393 0x21e4, 0x21e4, 0x21ea, 0x21ea, 0x21ec, 0x21ed, 0x21f0, 0x21f0,
394 0x2200, 0x2212, 0x2214, 0x2217, 0x221a, 0x221a, 0x2240, 0x227e,
395 0x2280, 0x228b, 0x22c0, 0x22c0, 0x22c4, 0x22ce, 0x22d0, 0x22d8,
396 0x22df, 0x22e6, 0x22e8, 0x22e9, 0x22ec, 0x22ec, 0x22f0, 0x22f7,
397 0x22ff, 0x22ff, 0x2340, 0x2343, 0x2440, 0x2440, 0x2444, 0x2444,
398 0x2448, 0x244d, 0x2468, 0x2469, 0x246c, 0x246d, 0x2470, 0x2470,
399 0x2472, 0x2472, 0x2474, 0x2475, 0x2479, 0x247a, 0x24c0, 0x24d3,
400 0x24e4, 0x24ef, 0x2500, 0x2509, 0x250c, 0x250c, 0x250e, 0x250e,
401 0x2510, 0x2511, 0x2514, 0x2515, 0x25e4, 0x25e4, 0x25ea, 0x25ea,
402 0x25ec, 0x25ed, 0x25f0, 0x25f0, 0x2600, 0x2612, 0x2614, 0x2617,
403 0x261a, 0x261a, 0x2640, 0x267e, 0x2680, 0x268b, 0x26c0, 0x26c0,
404 0x26c4, 0x26ce, 0x26d0, 0x26d8, 0x26df, 0x26e6, 0x26e8, 0x26e9,
405 0x26ec, 0x26ec, 0x26f0, 0x26f7, 0x26ff, 0x26ff, 0x2740, 0x2743,
406 0x300c, 0x300e, 0x301c, 0x301d, 0x302a, 0x302a, 0x302c, 0x302d,
407 0x3030, 0x3031, 0x3034, 0x3036, 0x303c, 0x303c, 0x305e, 0x305f,
411 #ifdef CONFIG_DEBUG_FS
412 static void a3xx_show(struct msm_gpu *gpu, struct seq_file *m)
414 seq_printf(m, "status: %08x\n",
415 gpu_read(gpu, REG_A3XX_RBBM_STATUS));
420 /* would be nice to not have to duplicate the _show() stuff with printk(): */
421 static void a3xx_dump(struct msm_gpu *gpu)
423 printk("status: %08x\n",
424 gpu_read(gpu, REG_A3XX_RBBM_STATUS));
427 /* Register offset defines for A3XX */
428 static const unsigned int a3xx_register_offsets[REG_ADRENO_REGISTER_MAX] = {
429 REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_BASE, REG_AXXX_CP_RB_BASE),
430 REG_ADRENO_SKIP(REG_ADRENO_CP_RB_BASE_HI),
431 REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_RPTR_ADDR, REG_AXXX_CP_RB_RPTR_ADDR),
432 REG_ADRENO_SKIP(REG_ADRENO_CP_RB_RPTR_ADDR_HI),
433 REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_RPTR, REG_AXXX_CP_RB_RPTR),
434 REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_WPTR, REG_AXXX_CP_RB_WPTR),
435 REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_CNTL, REG_AXXX_CP_RB_CNTL),
438 static const struct adreno_gpu_funcs funcs = {
440 .get_param = adreno_get_param,
441 .hw_init = a3xx_hw_init,
442 .pm_suspend = msm_gpu_pm_suspend,
443 .pm_resume = msm_gpu_pm_resume,
444 .recover = a3xx_recover,
445 .last_fence = adreno_last_fence,
446 .submit = adreno_submit,
447 .flush = adreno_flush,
449 .destroy = a3xx_destroy,
450 #ifdef CONFIG_DEBUG_FS
456 static const struct msm_gpu_perfcntr perfcntrs[] = {
457 { REG_A3XX_SP_PERFCOUNTER6_SELECT, REG_A3XX_RBBM_PERFCTR_SP_6_LO,
458 SP_ALU_ACTIVE_CYCLES, "ALUACTIVE" },
459 { REG_A3XX_SP_PERFCOUNTER7_SELECT, REG_A3XX_RBBM_PERFCTR_SP_7_LO,
460 SP_FS_FULL_ALU_INSTRUCTIONS, "ALUFULL" },
463 struct msm_gpu *a3xx_gpu_init(struct drm_device *dev)
465 struct a3xx_gpu *a3xx_gpu = NULL;
466 struct adreno_gpu *adreno_gpu;
468 struct msm_drm_private *priv = dev->dev_private;
469 struct platform_device *pdev = priv->gpu_pdev;
473 dev_err(dev->dev, "no a3xx device\n");
478 a3xx_gpu = kzalloc(sizeof(*a3xx_gpu), GFP_KERNEL);
484 adreno_gpu = &a3xx_gpu->base;
485 gpu = &adreno_gpu->base;
487 gpu->perfcntrs = perfcntrs;
488 gpu->num_perfcntrs = ARRAY_SIZE(perfcntrs);
490 adreno_gpu->registers = a3xx_registers;
491 adreno_gpu->reg_offsets = a3xx_register_offsets;
493 ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs);
497 /* if needed, allocate gmem: */
498 if (adreno_is_a330(adreno_gpu)) {
499 #ifdef CONFIG_MSM_OCMEM
500 /* TODO this is different/missing upstream: */
501 struct ocmem_buf *ocmem_hdl =
502 ocmem_allocate(OCMEM_GRAPHICS, adreno_gpu->gmem);
504 a3xx_gpu->ocmem_hdl = ocmem_hdl;
505 a3xx_gpu->ocmem_base = ocmem_hdl->addr;
506 adreno_gpu->gmem = ocmem_hdl->len;
507 DBG("using %dK of OCMEM at 0x%08x", adreno_gpu->gmem / 1024,
508 a3xx_gpu->ocmem_base);
513 /* TODO we think it is possible to configure the GPU to
514 * restrict access to VRAM carveout. But the required
515 * registers are unknown. For now just bail out and
516 * limp along with just modesetting. If it turns out
517 * to not be possible to restrict access, then we must
518 * implement a cmdstream validator.
520 dev_err(dev->dev, "No memory protection without IOMMU\n");
529 a3xx_destroy(&a3xx_gpu->base.base);