e6cb2bc40ebe73791bdee7e1e1892e6696b89301
[linux-2.6-block.git] / drivers / gpu / drm / msm / adreno / a3xx_gpu.c
1 /*
2  * Copyright (C) 2013 Red Hat
3  * Author: Rob Clark <robdclark@gmail.com>
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 as published by
7  * the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along with
15  * this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 #ifdef CONFIG_MSM_OCMEM
19 #  include <mach/ocmem.h>
20 #endif
21
22 #include "a3xx_gpu.h"
23
24 #define A3XX_INT0_MASK \
25         (A3XX_INT0_RBBM_AHB_ERROR |        \
26          A3XX_INT0_RBBM_ATB_BUS_OVERFLOW | \
27          A3XX_INT0_CP_T0_PACKET_IN_IB |    \
28          A3XX_INT0_CP_OPCODE_ERROR |       \
29          A3XX_INT0_CP_RESERVED_BIT_ERROR | \
30          A3XX_INT0_CP_HW_FAULT |           \
31          A3XX_INT0_CP_IB1_INT |            \
32          A3XX_INT0_CP_IB2_INT |            \
33          A3XX_INT0_CP_RB_INT |             \
34          A3XX_INT0_CP_REG_PROTECT_FAULT |  \
35          A3XX_INT0_CP_AHB_ERROR_HALT |     \
36          A3XX_INT0_UCHE_OOB_ACCESS)
37
38
39 static bool hang_debug = false;
40 MODULE_PARM_DESC(hang_debug, "Dump registers when hang is detected (can be slow!)");
41 module_param_named(hang_debug, hang_debug, bool, 0600);
42 static void a3xx_dump(struct msm_gpu *gpu);
43
44 static struct platform_device *a3xx_pdev;
45
46 static void a3xx_me_init(struct msm_gpu *gpu)
47 {
48         struct msm_ringbuffer *ring = gpu->rb;
49
50         OUT_PKT3(ring, CP_ME_INIT, 17);
51         OUT_RING(ring, 0x000003f7);
52         OUT_RING(ring, 0x00000000);
53         OUT_RING(ring, 0x00000000);
54         OUT_RING(ring, 0x00000000);
55         OUT_RING(ring, 0x00000080);
56         OUT_RING(ring, 0x00000100);
57         OUT_RING(ring, 0x00000180);
58         OUT_RING(ring, 0x00006600);
59         OUT_RING(ring, 0x00000150);
60         OUT_RING(ring, 0x0000014e);
61         OUT_RING(ring, 0x00000154);
62         OUT_RING(ring, 0x00000001);
63         OUT_RING(ring, 0x00000000);
64         OUT_RING(ring, 0x00000000);
65         OUT_RING(ring, 0x00000000);
66         OUT_RING(ring, 0x00000000);
67         OUT_RING(ring, 0x00000000);
68
69         gpu->funcs->flush(gpu);
70         gpu->funcs->idle(gpu);
71 }
72
73 static int a3xx_hw_init(struct msm_gpu *gpu)
74 {
75         struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
76         struct a3xx_gpu *a3xx_gpu = to_a3xx_gpu(adreno_gpu);
77         uint32_t *ptr, len;
78         int i, ret;
79
80         DBG("%s", gpu->name);
81
82         if (adreno_is_a305(adreno_gpu)) {
83                 /* Set up 16 deep read/write request queues: */
84                 gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF0, 0x10101010);
85                 gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF1, 0x10101010);
86                 gpu_write(gpu, REG_A3XX_VBIF_OUT_RD_LIM_CONF0, 0x10101010);
87                 gpu_write(gpu, REG_A3XX_VBIF_OUT_WR_LIM_CONF0, 0x10101010);
88                 gpu_write(gpu, REG_A3XX_VBIF_DDR_OUT_MAX_BURST, 0x0000303);
89                 gpu_write(gpu, REG_A3XX_VBIF_IN_WR_LIM_CONF0, 0x10101010);
90                 gpu_write(gpu, REG_A3XX_VBIF_IN_WR_LIM_CONF1, 0x10101010);
91                 /* Enable WR-REQ: */
92                 gpu_write(gpu, REG_A3XX_VBIF_GATE_OFF_WRREQ_EN, 0x0000ff);
93                 /* Set up round robin arbitration between both AXI ports: */
94                 gpu_write(gpu, REG_A3XX_VBIF_ARB_CTL, 0x00000030);
95                 /* Set up AOOO: */
96                 gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO_EN, 0x0000003c);
97                 gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO, 0x003c003c);
98
99         } else if (adreno_is_a320(adreno_gpu)) {
100                 /* Set up 16 deep read/write request queues: */
101                 gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF0, 0x10101010);
102                 gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF1, 0x10101010);
103                 gpu_write(gpu, REG_A3XX_VBIF_OUT_RD_LIM_CONF0, 0x10101010);
104                 gpu_write(gpu, REG_A3XX_VBIF_OUT_WR_LIM_CONF0, 0x10101010);
105                 gpu_write(gpu, REG_A3XX_VBIF_DDR_OUT_MAX_BURST, 0x0000303);
106                 gpu_write(gpu, REG_A3XX_VBIF_IN_WR_LIM_CONF0, 0x10101010);
107                 gpu_write(gpu, REG_A3XX_VBIF_IN_WR_LIM_CONF1, 0x10101010);
108                 /* Enable WR-REQ: */
109                 gpu_write(gpu, REG_A3XX_VBIF_GATE_OFF_WRREQ_EN, 0x0000ff);
110                 /* Set up round robin arbitration between both AXI ports: */
111                 gpu_write(gpu, REG_A3XX_VBIF_ARB_CTL, 0x00000030);
112                 /* Set up AOOO: */
113                 gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO_EN, 0x0000003c);
114                 gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO, 0x003c003c);
115                 /* Enable 1K sort: */
116                 gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT, 0x000000ff);
117                 gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT_CONF, 0x000000a4);
118
119         } else if (adreno_is_a330v2(adreno_gpu)) {
120                 /*
121                  * Most of the VBIF registers on 8974v2 have the correct
122                  * values at power on, so we won't modify those if we don't
123                  * need to
124                  */
125                 /* Enable 1k sort: */
126                 gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT, 0x0001003f);
127                 gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT_CONF, 0x000000a4);
128                 /* Enable WR-REQ: */
129                 gpu_write(gpu, REG_A3XX_VBIF_GATE_OFF_WRREQ_EN, 0x00003f);
130                 gpu_write(gpu, REG_A3XX_VBIF_DDR_OUT_MAX_BURST, 0x0000303);
131                 /* Set up VBIF_ROUND_ROBIN_QOS_ARB: */
132                 gpu_write(gpu, REG_A3XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x0003);
133
134         } else if (adreno_is_a330(adreno_gpu)) {
135                 /* Set up 16 deep read/write request queues: */
136                 gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF0, 0x18181818);
137                 gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF1, 0x18181818);
138                 gpu_write(gpu, REG_A3XX_VBIF_OUT_RD_LIM_CONF0, 0x18181818);
139                 gpu_write(gpu, REG_A3XX_VBIF_OUT_WR_LIM_CONF0, 0x18181818);
140                 gpu_write(gpu, REG_A3XX_VBIF_DDR_OUT_MAX_BURST, 0x0000303);
141                 gpu_write(gpu, REG_A3XX_VBIF_IN_WR_LIM_CONF0, 0x18181818);
142                 gpu_write(gpu, REG_A3XX_VBIF_IN_WR_LIM_CONF1, 0x18181818);
143                 /* Enable WR-REQ: */
144                 gpu_write(gpu, REG_A3XX_VBIF_GATE_OFF_WRREQ_EN, 0x00003f);
145                 /* Set up round robin arbitration between both AXI ports: */
146                 gpu_write(gpu, REG_A3XX_VBIF_ARB_CTL, 0x00000030);
147                 /* Set up VBIF_ROUND_ROBIN_QOS_ARB: */
148                 gpu_write(gpu, REG_A3XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x0001);
149                 /* Set up AOOO: */
150                 gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO_EN, 0x0000003f);
151                 gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO, 0x003f003f);
152                 /* Enable 1K sort: */
153                 gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT, 0x0001003f);
154                 gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT_CONF, 0x000000a4);
155                 /* Disable VBIF clock gating. This is to enable AXI running
156                  * higher frequency than GPU:
157                  */
158                 gpu_write(gpu, REG_A3XX_VBIF_CLKON, 0x00000001);
159
160         } else {
161                 BUG();
162         }
163
164         /* Make all blocks contribute to the GPU BUSY perf counter: */
165         gpu_write(gpu, REG_A3XX_RBBM_GPU_BUSY_MASKED, 0xffffffff);
166
167         /* Tune the hystersis counters for SP and CP idle detection: */
168         gpu_write(gpu, REG_A3XX_RBBM_SP_HYST_CNT, 0x10);
169         gpu_write(gpu, REG_A3XX_RBBM_WAIT_IDLE_CLOCKS_CTL, 0x10);
170
171         /* Enable the RBBM error reporting bits.  This lets us get
172          * useful information on failure:
173          */
174         gpu_write(gpu, REG_A3XX_RBBM_AHB_CTL0, 0x00000001);
175
176         /* Enable AHB error reporting: */
177         gpu_write(gpu, REG_A3XX_RBBM_AHB_CTL1, 0xa6ffffff);
178
179         /* Turn on the power counters: */
180         gpu_write(gpu, REG_A3XX_RBBM_RBBM_CTL, 0x00030000);
181
182         /* Turn on hang detection - this spews a lot of useful information
183          * into the RBBM registers on a hang:
184          */
185         gpu_write(gpu, REG_A3XX_RBBM_INTERFACE_HANG_INT_CTL, 0x00010fff);
186
187         /* Enable 64-byte cacheline size. HW Default is 32-byte (0x000000E0): */
188         gpu_write(gpu, REG_A3XX_UCHE_CACHE_MODE_CONTROL_REG, 0x00000001);
189
190         /* Enable Clock gating: */
191         if (adreno_is_a320(adreno_gpu))
192                 gpu_write(gpu, REG_A3XX_RBBM_CLOCK_CTL, 0xbfffffff);
193         else if (adreno_is_a330v2(adreno_gpu))
194                 gpu_write(gpu, REG_A3XX_RBBM_CLOCK_CTL, 0xaaaaaaaa);
195         else if (adreno_is_a330(adreno_gpu))
196                 gpu_write(gpu, REG_A3XX_RBBM_CLOCK_CTL, 0xbffcffff);
197
198         if (adreno_is_a330v2(adreno_gpu))
199                 gpu_write(gpu, REG_A3XX_RBBM_GPR0_CTL, 0x05515455);
200         else if (adreno_is_a330(adreno_gpu))
201                 gpu_write(gpu, REG_A3XX_RBBM_GPR0_CTL, 0x00000000);
202
203         /* Set the OCMEM base address for A330, etc */
204         if (a3xx_gpu->ocmem_hdl) {
205                 gpu_write(gpu, REG_A3XX_RB_GMEM_BASE_ADDR,
206                         (unsigned int)(a3xx_gpu->ocmem_base >> 14));
207         }
208
209         /* Turn on performance counters: */
210         gpu_write(gpu, REG_A3XX_RBBM_PERFCTR_CTL, 0x01);
211
212         /* Set SP perfcounter 7 to count SP_FS_FULL_ALU_INSTRUCTIONS
213          * we will use this to augment our hang detection:
214          */
215         gpu_write(gpu, REG_A3XX_SP_PERFCOUNTER7_SELECT,
216                         SP_FS_FULL_ALU_INSTRUCTIONS);
217
218         gpu_write(gpu, REG_A3XX_RBBM_INT_0_MASK, A3XX_INT0_MASK);
219
220         ret = adreno_hw_init(gpu);
221         if (ret)
222                 return ret;
223
224         /* setup access protection: */
225         gpu_write(gpu, REG_A3XX_CP_PROTECT_CTRL, 0x00000007);
226
227         /* RBBM registers */
228         gpu_write(gpu, REG_A3XX_CP_PROTECT(0), 0x63000040);
229         gpu_write(gpu, REG_A3XX_CP_PROTECT(1), 0x62000080);
230         gpu_write(gpu, REG_A3XX_CP_PROTECT(2), 0x600000cc);
231         gpu_write(gpu, REG_A3XX_CP_PROTECT(3), 0x60000108);
232         gpu_write(gpu, REG_A3XX_CP_PROTECT(4), 0x64000140);
233         gpu_write(gpu, REG_A3XX_CP_PROTECT(5), 0x66000400);
234
235         /* CP registers */
236         gpu_write(gpu, REG_A3XX_CP_PROTECT(6), 0x65000700);
237         gpu_write(gpu, REG_A3XX_CP_PROTECT(7), 0x610007d8);
238         gpu_write(gpu, REG_A3XX_CP_PROTECT(8), 0x620007e0);
239         gpu_write(gpu, REG_A3XX_CP_PROTECT(9), 0x61001178);
240         gpu_write(gpu, REG_A3XX_CP_PROTECT(10), 0x64001180);
241
242         /* RB registers */
243         gpu_write(gpu, REG_A3XX_CP_PROTECT(11), 0x60003300);
244
245         /* VBIF registers */
246         gpu_write(gpu, REG_A3XX_CP_PROTECT(12), 0x6b00c000);
247
248         /* NOTE: PM4/micro-engine firmware registers look to be the same
249          * for a2xx and a3xx.. we could possibly push that part down to
250          * adreno_gpu base class.  Or push both PM4 and PFP but
251          * parameterize the pfp ucode addr/data registers..
252          */
253
254         /* Load PM4: */
255         ptr = (uint32_t *)(adreno_gpu->pm4->data);
256         len = adreno_gpu->pm4->size / 4;
257         DBG("loading PM4 ucode version: %x", ptr[1]);
258
259         gpu_write(gpu, REG_AXXX_CP_DEBUG,
260                         AXXX_CP_DEBUG_DYNAMIC_CLK_DISABLE |
261                         AXXX_CP_DEBUG_MIU_128BIT_WRITE_ENABLE);
262         gpu_write(gpu, REG_AXXX_CP_ME_RAM_WADDR, 0);
263         for (i = 1; i < len; i++)
264                 gpu_write(gpu, REG_AXXX_CP_ME_RAM_DATA, ptr[i]);
265
266         /* Load PFP: */
267         ptr = (uint32_t *)(adreno_gpu->pfp->data);
268         len = adreno_gpu->pfp->size / 4;
269         DBG("loading PFP ucode version: %x", ptr[5]);
270
271         gpu_write(gpu, REG_A3XX_CP_PFP_UCODE_ADDR, 0);
272         for (i = 1; i < len; i++)
273                 gpu_write(gpu, REG_A3XX_CP_PFP_UCODE_DATA, ptr[i]);
274
275         /* CP ROQ queue sizes (bytes) - RB:16, ST:16, IB1:32, IB2:64 */
276         if (adreno_is_a305(adreno_gpu) || adreno_is_a320(adreno_gpu)) {
277                 gpu_write(gpu, REG_AXXX_CP_QUEUE_THRESHOLDS,
278                                 AXXX_CP_QUEUE_THRESHOLDS_CSQ_IB1_START(2) |
279                                 AXXX_CP_QUEUE_THRESHOLDS_CSQ_IB2_START(6) |
280                                 AXXX_CP_QUEUE_THRESHOLDS_CSQ_ST_START(14));
281         } else if (adreno_is_a330(adreno_gpu)) {
282                 /* NOTE: this (value take from downstream android driver)
283                  * includes some bits outside of the known bitfields.  But
284                  * A330 has this "MERCIU queue" thing too, which might
285                  * explain a new bitfield or reshuffling:
286                  */
287                 gpu_write(gpu, REG_AXXX_CP_QUEUE_THRESHOLDS, 0x003e2008);
288         }
289
290         /* clear ME_HALT to start micro engine */
291         gpu_write(gpu, REG_AXXX_CP_ME_CNTL, 0);
292
293         a3xx_me_init(gpu);
294
295         return 0;
296 }
297
298 static void a3xx_recover(struct msm_gpu *gpu)
299 {
300         /* dump registers before resetting gpu, if enabled: */
301         if (hang_debug)
302                 a3xx_dump(gpu);
303         gpu_write(gpu, REG_A3XX_RBBM_SW_RESET_CMD, 1);
304         gpu_read(gpu, REG_A3XX_RBBM_SW_RESET_CMD);
305         gpu_write(gpu, REG_A3XX_RBBM_SW_RESET_CMD, 0);
306         adreno_recover(gpu);
307 }
308
309 static void a3xx_destroy(struct msm_gpu *gpu)
310 {
311         struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
312         struct a3xx_gpu *a3xx_gpu = to_a3xx_gpu(adreno_gpu);
313
314         DBG("%s", gpu->name);
315
316         adreno_gpu_cleanup(adreno_gpu);
317
318 #ifdef CONFIG_MSM_OCMEM
319         if (a3xx_gpu->ocmem_base)
320                 ocmem_free(OCMEM_GRAPHICS, a3xx_gpu->ocmem_hdl);
321 #endif
322
323         put_device(&a3xx_gpu->pdev->dev);
324         kfree(a3xx_gpu);
325 }
326
327 static void a3xx_idle(struct msm_gpu *gpu)
328 {
329         /* wait for ringbuffer to drain: */
330         adreno_idle(gpu);
331
332         /* then wait for GPU to finish: */
333         if (spin_until(!(gpu_read(gpu, REG_A3XX_RBBM_STATUS) &
334                         A3XX_RBBM_STATUS_GPU_BUSY)))
335                 DRM_ERROR("%s: timeout waiting for GPU to idle!\n", gpu->name);
336
337         /* TODO maybe we need to reset GPU here to recover from hang? */
338 }
339
340 static irqreturn_t a3xx_irq(struct msm_gpu *gpu)
341 {
342         uint32_t status;
343
344         status = gpu_read(gpu, REG_A3XX_RBBM_INT_0_STATUS);
345         DBG("%s: %08x", gpu->name, status);
346
347         // TODO
348
349         gpu_write(gpu, REG_A3XX_RBBM_INT_CLEAR_CMD, status);
350
351         msm_gpu_retire(gpu);
352
353         return IRQ_HANDLED;
354 }
355
356 static const unsigned int a3xx_registers[] = {
357         0x0000, 0x0002, 0x0010, 0x0012, 0x0018, 0x0018, 0x0020, 0x0027,
358         0x0029, 0x002b, 0x002e, 0x0033, 0x0040, 0x0042, 0x0050, 0x005c,
359         0x0060, 0x006c, 0x0080, 0x0082, 0x0084, 0x0088, 0x0090, 0x00e5,
360         0x00ea, 0x00ed, 0x0100, 0x0100, 0x0110, 0x0123, 0x01c0, 0x01c1,
361         0x01c3, 0x01c5, 0x01c7, 0x01c7, 0x01d5, 0x01d9, 0x01dc, 0x01dd,
362         0x01ea, 0x01ea, 0x01ee, 0x01f1, 0x01f5, 0x01f5, 0x01fc, 0x01ff,
363         0x0440, 0x0440, 0x0443, 0x0443, 0x0445, 0x0445, 0x044d, 0x044f,
364         0x0452, 0x0452, 0x0454, 0x046f, 0x047c, 0x047c, 0x047f, 0x047f,
365         0x0578, 0x057f, 0x0600, 0x0602, 0x0605, 0x0607, 0x060a, 0x060e,
366         0x0612, 0x0614, 0x0c01, 0x0c02, 0x0c06, 0x0c1d, 0x0c3d, 0x0c3f,
367         0x0c48, 0x0c4b, 0x0c80, 0x0c80, 0x0c88, 0x0c8b, 0x0ca0, 0x0cb7,
368         0x0cc0, 0x0cc1, 0x0cc6, 0x0cc7, 0x0ce4, 0x0ce5, 0x0e00, 0x0e05,
369         0x0e0c, 0x0e0c, 0x0e22, 0x0e23, 0x0e41, 0x0e45, 0x0e64, 0x0e65,
370         0x0e80, 0x0e82, 0x0e84, 0x0e89, 0x0ea0, 0x0ea1, 0x0ea4, 0x0ea7,
371         0x0ec4, 0x0ecb, 0x0ee0, 0x0ee0, 0x0f00, 0x0f01, 0x0f03, 0x0f09,
372         0x2040, 0x2040, 0x2044, 0x2044, 0x2048, 0x204d, 0x2068, 0x2069,
373         0x206c, 0x206d, 0x2070, 0x2070, 0x2072, 0x2072, 0x2074, 0x2075,
374         0x2079, 0x207a, 0x20c0, 0x20d3, 0x20e4, 0x20ef, 0x2100, 0x2109,
375         0x210c, 0x210c, 0x210e, 0x210e, 0x2110, 0x2111, 0x2114, 0x2115,
376         0x21e4, 0x21e4, 0x21ea, 0x21ea, 0x21ec, 0x21ed, 0x21f0, 0x21f0,
377         0x2200, 0x2212, 0x2214, 0x2217, 0x221a, 0x221a, 0x2240, 0x227e,
378         0x2280, 0x228b, 0x22c0, 0x22c0, 0x22c4, 0x22ce, 0x22d0, 0x22d8,
379         0x22df, 0x22e6, 0x22e8, 0x22e9, 0x22ec, 0x22ec, 0x22f0, 0x22f7,
380         0x22ff, 0x22ff, 0x2340, 0x2343, 0x2348, 0x2349, 0x2350, 0x2356,
381         0x2360, 0x2360, 0x2440, 0x2440, 0x2444, 0x2444, 0x2448, 0x244d,
382         0x2468, 0x2469, 0x246c, 0x246d, 0x2470, 0x2470, 0x2472, 0x2472,
383         0x2474, 0x2475, 0x2479, 0x247a, 0x24c0, 0x24d3, 0x24e4, 0x24ef,
384         0x2500, 0x2509, 0x250c, 0x250c, 0x250e, 0x250e, 0x2510, 0x2511,
385         0x2514, 0x2515, 0x25e4, 0x25e4, 0x25ea, 0x25ea, 0x25ec, 0x25ed,
386         0x25f0, 0x25f0, 0x2600, 0x2612, 0x2614, 0x2617, 0x261a, 0x261a,
387         0x2640, 0x267e, 0x2680, 0x268b, 0x26c0, 0x26c0, 0x26c4, 0x26ce,
388         0x26d0, 0x26d8, 0x26df, 0x26e6, 0x26e8, 0x26e9, 0x26ec, 0x26ec,
389         0x26f0, 0x26f7, 0x26ff, 0x26ff, 0x2740, 0x2743, 0x2748, 0x2749,
390         0x2750, 0x2756, 0x2760, 0x2760, 0x300c, 0x300e, 0x301c, 0x301d,
391         0x302a, 0x302a, 0x302c, 0x302d, 0x3030, 0x3031, 0x3034, 0x3036,
392         0x303c, 0x303c, 0x305e, 0x305f,
393 };
394
395 #ifdef CONFIG_DEBUG_FS
396 static void a3xx_show(struct msm_gpu *gpu, struct seq_file *m)
397 {
398         struct drm_device *dev = gpu->dev;
399         int i;
400
401         adreno_show(gpu, m);
402
403         mutex_lock(&dev->struct_mutex);
404
405         gpu->funcs->pm_resume(gpu);
406
407         seq_printf(m, "status:   %08x\n",
408                         gpu_read(gpu, REG_A3XX_RBBM_STATUS));
409
410         /* dump these out in a form that can be parsed by demsm: */
411         seq_printf(m, "IO:region %s 00000000 00020000\n", gpu->name);
412         for (i = 0; i < ARRAY_SIZE(a3xx_registers); i += 2) {
413                 uint32_t start = a3xx_registers[i];
414                 uint32_t end   = a3xx_registers[i+1];
415                 uint32_t addr;
416
417                 for (addr = start; addr <= end; addr++) {
418                         uint32_t val = gpu_read(gpu, addr);
419                         seq_printf(m, "IO:R %08x %08x\n", addr<<2, val);
420                 }
421         }
422
423         gpu->funcs->pm_suspend(gpu);
424
425         mutex_unlock(&dev->struct_mutex);
426 }
427 #endif
428
429 /* would be nice to not have to duplicate the _show() stuff with printk(): */
430 static void a3xx_dump(struct msm_gpu *gpu)
431 {
432         int i;
433
434         adreno_dump(gpu);
435         printk("status:   %08x\n",
436                         gpu_read(gpu, REG_A3XX_RBBM_STATUS));
437
438         /* dump these out in a form that can be parsed by demsm: */
439         printk("IO:region %s 00000000 00020000\n", gpu->name);
440         for (i = 0; i < ARRAY_SIZE(a3xx_registers); i += 2) {
441                 uint32_t start = a3xx_registers[i];
442                 uint32_t end   = a3xx_registers[i+1];
443                 uint32_t addr;
444
445                 for (addr = start; addr <= end; addr++) {
446                         uint32_t val = gpu_read(gpu, addr);
447                         printk("IO:R %08x %08x\n", addr<<2, val);
448                 }
449         }
450 }
451
452 static const struct adreno_gpu_funcs funcs = {
453         .base = {
454                 .get_param = adreno_get_param,
455                 .hw_init = a3xx_hw_init,
456                 .pm_suspend = msm_gpu_pm_suspend,
457                 .pm_resume = msm_gpu_pm_resume,
458                 .recover = a3xx_recover,
459                 .last_fence = adreno_last_fence,
460                 .submit = adreno_submit,
461                 .flush = adreno_flush,
462                 .idle = a3xx_idle,
463                 .irq = a3xx_irq,
464                 .destroy = a3xx_destroy,
465 #ifdef CONFIG_DEBUG_FS
466                 .show = a3xx_show,
467 #endif
468         },
469 };
470
471 struct msm_gpu *a3xx_gpu_init(struct drm_device *dev)
472 {
473         struct a3xx_gpu *a3xx_gpu = NULL;
474         struct adreno_gpu *adreno_gpu;
475         struct msm_gpu *gpu;
476         struct platform_device *pdev = a3xx_pdev;
477         struct adreno_platform_config *config;
478         int ret;
479
480         if (!pdev) {
481                 dev_err(dev->dev, "no a3xx device\n");
482                 ret = -ENXIO;
483                 goto fail;
484         }
485
486         config = pdev->dev.platform_data;
487
488         a3xx_gpu = kzalloc(sizeof(*a3xx_gpu), GFP_KERNEL);
489         if (!a3xx_gpu) {
490                 ret = -ENOMEM;
491                 goto fail;
492         }
493
494         adreno_gpu = &a3xx_gpu->base;
495         gpu = &adreno_gpu->base;
496
497         get_device(&pdev->dev);
498         a3xx_gpu->pdev = pdev;
499
500         gpu->fast_rate = config->fast_rate;
501         gpu->slow_rate = config->slow_rate;
502         gpu->bus_freq  = config->bus_freq;
503 #ifdef CONFIG_MSM_BUS_SCALING
504         gpu->bus_scale_table = config->bus_scale_table;
505 #endif
506
507         DBG("fast_rate=%u, slow_rate=%u, bus_freq=%u",
508                         gpu->fast_rate, gpu->slow_rate, gpu->bus_freq);
509
510         ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, config->rev);
511         if (ret)
512                 goto fail;
513
514         /* if needed, allocate gmem: */
515         if (adreno_is_a330(adreno_gpu)) {
516 #ifdef CONFIG_MSM_OCMEM
517                 /* TODO this is different/missing upstream: */
518                 struct ocmem_buf *ocmem_hdl =
519                                 ocmem_allocate(OCMEM_GRAPHICS, adreno_gpu->gmem);
520
521                 a3xx_gpu->ocmem_hdl = ocmem_hdl;
522                 a3xx_gpu->ocmem_base = ocmem_hdl->addr;
523                 adreno_gpu->gmem = ocmem_hdl->len;
524                 DBG("using %dK of OCMEM at 0x%08x", adreno_gpu->gmem / 1024,
525                                 a3xx_gpu->ocmem_base);
526 #endif
527         }
528
529         if (!gpu->mmu) {
530                 /* TODO we think it is possible to configure the GPU to
531                  * restrict access to VRAM carveout.  But the required
532                  * registers are unknown.  For now just bail out and
533                  * limp along with just modesetting.  If it turns out
534                  * to not be possible to restrict access, then we must
535                  * implement a cmdstream validator.
536                  */
537                 dev_err(dev->dev, "No memory protection without IOMMU\n");
538                 ret = -ENXIO;
539                 goto fail;
540         }
541
542         return gpu;
543
544 fail:
545         if (a3xx_gpu)
546                 a3xx_destroy(&a3xx_gpu->base.base);
547
548         return ERR_PTR(ret);
549 }
550
551 /*
552  * The a3xx device:
553  */
554
555 #if defined(CONFIG_MSM_BUS_SCALING) && !defined(CONFIG_OF)
556 #  include <mach/kgsl.h>
557 #endif
558
559 static int a3xx_probe(struct platform_device *pdev)
560 {
561         static struct adreno_platform_config config = {};
562 #ifdef CONFIG_OF
563         struct device_node *child, *node = pdev->dev.of_node;
564         u32 val;
565         int ret;
566
567         ret = of_property_read_u32(node, "qcom,chipid", &val);
568         if (ret) {
569                 dev_err(&pdev->dev, "could not find chipid: %d\n", ret);
570                 return ret;
571         }
572
573         config.rev = ADRENO_REV((val >> 24) & 0xff,
574                         (val >> 16) & 0xff, (val >> 8) & 0xff, val & 0xff);
575
576         /* find clock rates: */
577         config.fast_rate = 0;
578         config.slow_rate = ~0;
579         for_each_child_of_node(node, child) {
580                 if (of_device_is_compatible(child, "qcom,gpu-pwrlevels")) {
581                         struct device_node *pwrlvl;
582                         for_each_child_of_node(child, pwrlvl) {
583                                 ret = of_property_read_u32(pwrlvl, "qcom,gpu-freq", &val);
584                                 if (ret) {
585                                         dev_err(&pdev->dev, "could not find gpu-freq: %d\n", ret);
586                                         return ret;
587                                 }
588                                 config.fast_rate = max(config.fast_rate, val);
589                                 config.slow_rate = min(config.slow_rate, val);
590                         }
591                 }
592         }
593
594         if (!config.fast_rate) {
595                 dev_err(&pdev->dev, "could not find clk rates\n");
596                 return -ENXIO;
597         }
598
599 #else
600         struct kgsl_device_platform_data *pdata = pdev->dev.platform_data;
601         uint32_t version = socinfo_get_version();
602         if (cpu_is_apq8064ab()) {
603                 config.fast_rate = 450000000;
604                 config.slow_rate = 27000000;
605                 config.bus_freq  = 4;
606                 config.rev = ADRENO_REV(3, 2, 1, 0);
607         } else if (cpu_is_apq8064()) {
608                 config.fast_rate = 400000000;
609                 config.slow_rate = 27000000;
610                 config.bus_freq  = 4;
611
612                 if (SOCINFO_VERSION_MAJOR(version) == 2)
613                         config.rev = ADRENO_REV(3, 2, 0, 2);
614                 else if ((SOCINFO_VERSION_MAJOR(version) == 1) &&
615                                 (SOCINFO_VERSION_MINOR(version) == 1))
616                         config.rev = ADRENO_REV(3, 2, 0, 1);
617                 else
618                         config.rev = ADRENO_REV(3, 2, 0, 0);
619
620         } else if (cpu_is_msm8960ab()) {
621                 config.fast_rate = 400000000;
622                 config.slow_rate = 320000000;
623                 config.bus_freq  = 4;
624
625                 if (SOCINFO_VERSION_MINOR(version) == 0)
626                         config.rev = ADRENO_REV(3, 2, 1, 0);
627                 else
628                         config.rev = ADRENO_REV(3, 2, 1, 1);
629
630         } else if (cpu_is_msm8930()) {
631                 config.fast_rate = 400000000;
632                 config.slow_rate = 27000000;
633                 config.bus_freq  = 3;
634
635                 if ((SOCINFO_VERSION_MAJOR(version) == 1) &&
636                         (SOCINFO_VERSION_MINOR(version) == 2))
637                         config.rev = ADRENO_REV(3, 0, 5, 2);
638                 else
639                         config.rev = ADRENO_REV(3, 0, 5, 0);
640
641         }
642 #  ifdef CONFIG_MSM_BUS_SCALING
643         config.bus_scale_table = pdata->bus_scale_table;
644 #  endif
645 #endif
646         pdev->dev.platform_data = &config;
647         a3xx_pdev = pdev;
648         return 0;
649 }
650
651 static int a3xx_remove(struct platform_device *pdev)
652 {
653         a3xx_pdev = NULL;
654         return 0;
655 }
656
657 static const struct of_device_id dt_match[] = {
658         { .compatible = "qcom,kgsl-3d0" },
659         {}
660 };
661 MODULE_DEVICE_TABLE(of, dt_match);
662
663 static struct platform_driver a3xx_driver = {
664         .probe = a3xx_probe,
665         .remove = a3xx_remove,
666         .driver = {
667                 .name = "kgsl-3d0",
668                 .of_match_table = dt_match,
669         },
670 };
671
672 void __init a3xx_register(void)
673 {
674         platform_driver_register(&a3xx_driver);
675 }
676
677 void __exit a3xx_unregister(void)
678 {
679         platform_driver_unregister(&a3xx_driver);
680 }