Linux Audio

Check our new training course

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