xref: /linux/drivers/gpu/drm/msm/adreno/a3xx_gpu.c (revision 0963756fe51313a1e2d76885cd21624d3b2cfbf2)
17198e6b0SRob Clark /*
27198e6b0SRob Clark  * Copyright (C) 2013 Red Hat
37198e6b0SRob Clark  * Author: Rob Clark <robdclark@gmail.com>
47198e6b0SRob Clark  *
57198e6b0SRob Clark  * This program is free software; you can redistribute it and/or modify it
67198e6b0SRob Clark  * under the terms of the GNU General Public License version 2 as published by
77198e6b0SRob Clark  * the Free Software Foundation.
87198e6b0SRob Clark  *
97198e6b0SRob Clark  * This program is distributed in the hope that it will be useful, but WITHOUT
107198e6b0SRob Clark  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
117198e6b0SRob Clark  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
127198e6b0SRob Clark  * more details.
137198e6b0SRob Clark  *
147198e6b0SRob Clark  * You should have received a copy of the GNU General Public License along with
157198e6b0SRob Clark  * this program.  If not, see <http://www.gnu.org/licenses/>.
167198e6b0SRob Clark  */
177198e6b0SRob Clark 
1855459968SRob Clark #ifdef CONFIG_MSM_OCMEM
1955459968SRob Clark #  include <mach/ocmem.h>
2055459968SRob Clark #endif
2155459968SRob Clark 
227198e6b0SRob Clark #include "a3xx_gpu.h"
237198e6b0SRob Clark 
247198e6b0SRob Clark #define A3XX_INT0_MASK \
257198e6b0SRob Clark 	(A3XX_INT0_RBBM_AHB_ERROR |        \
267198e6b0SRob Clark 	 A3XX_INT0_RBBM_ATB_BUS_OVERFLOW | \
277198e6b0SRob Clark 	 A3XX_INT0_CP_T0_PACKET_IN_IB |    \
287198e6b0SRob Clark 	 A3XX_INT0_CP_OPCODE_ERROR |       \
297198e6b0SRob Clark 	 A3XX_INT0_CP_RESERVED_BIT_ERROR | \
307198e6b0SRob Clark 	 A3XX_INT0_CP_HW_FAULT |           \
317198e6b0SRob Clark 	 A3XX_INT0_CP_IB1_INT |            \
327198e6b0SRob Clark 	 A3XX_INT0_CP_IB2_INT |            \
337198e6b0SRob Clark 	 A3XX_INT0_CP_RB_INT |             \
347198e6b0SRob Clark 	 A3XX_INT0_CP_REG_PROTECT_FAULT |  \
357198e6b0SRob Clark 	 A3XX_INT0_CP_AHB_ERROR_HALT |     \
367198e6b0SRob Clark 	 A3XX_INT0_UCHE_OOB_ACCESS)
377198e6b0SRob Clark 
385b6ef08eSRob Clark 
395b6ef08eSRob Clark static bool hang_debug = false;
405b6ef08eSRob Clark MODULE_PARM_DESC(hang_debug, "Dump registers when hang is detected (can be slow!)");
415b6ef08eSRob Clark module_param_named(hang_debug, hang_debug, bool, 0600);
425b6ef08eSRob Clark static void a3xx_dump(struct msm_gpu *gpu);
435b6ef08eSRob Clark 
447198e6b0SRob Clark static struct platform_device *a3xx_pdev;
457198e6b0SRob Clark 
467198e6b0SRob Clark static void a3xx_me_init(struct msm_gpu *gpu)
477198e6b0SRob Clark {
487198e6b0SRob Clark 	struct msm_ringbuffer *ring = gpu->rb;
497198e6b0SRob Clark 
507198e6b0SRob Clark 	OUT_PKT3(ring, CP_ME_INIT, 17);
517198e6b0SRob Clark 	OUT_RING(ring, 0x000003f7);
527198e6b0SRob Clark 	OUT_RING(ring, 0x00000000);
537198e6b0SRob Clark 	OUT_RING(ring, 0x00000000);
547198e6b0SRob Clark 	OUT_RING(ring, 0x00000000);
557198e6b0SRob Clark 	OUT_RING(ring, 0x00000080);
567198e6b0SRob Clark 	OUT_RING(ring, 0x00000100);
577198e6b0SRob Clark 	OUT_RING(ring, 0x00000180);
587198e6b0SRob Clark 	OUT_RING(ring, 0x00006600);
597198e6b0SRob Clark 	OUT_RING(ring, 0x00000150);
607198e6b0SRob Clark 	OUT_RING(ring, 0x0000014e);
617198e6b0SRob Clark 	OUT_RING(ring, 0x00000154);
627198e6b0SRob Clark 	OUT_RING(ring, 0x00000001);
637198e6b0SRob Clark 	OUT_RING(ring, 0x00000000);
647198e6b0SRob Clark 	OUT_RING(ring, 0x00000000);
657198e6b0SRob Clark 	OUT_RING(ring, 0x00000000);
667198e6b0SRob Clark 	OUT_RING(ring, 0x00000000);
677198e6b0SRob Clark 	OUT_RING(ring, 0x00000000);
687198e6b0SRob Clark 
697198e6b0SRob Clark 	gpu->funcs->flush(gpu);
707198e6b0SRob Clark 	gpu->funcs->idle(gpu);
717198e6b0SRob Clark }
727198e6b0SRob Clark 
737198e6b0SRob Clark static int a3xx_hw_init(struct msm_gpu *gpu)
747198e6b0SRob Clark {
757198e6b0SRob Clark 	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
7655459968SRob Clark 	struct a3xx_gpu *a3xx_gpu = to_a3xx_gpu(adreno_gpu);
777198e6b0SRob Clark 	uint32_t *ptr, len;
787198e6b0SRob Clark 	int i, ret;
797198e6b0SRob Clark 
807198e6b0SRob Clark 	DBG("%s", gpu->name);
817198e6b0SRob Clark 
827198e6b0SRob Clark 	if (adreno_is_a305(adreno_gpu)) {
837198e6b0SRob Clark 		/* Set up 16 deep read/write request queues: */
847198e6b0SRob Clark 		gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF0, 0x10101010);
857198e6b0SRob Clark 		gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF1, 0x10101010);
867198e6b0SRob Clark 		gpu_write(gpu, REG_A3XX_VBIF_OUT_RD_LIM_CONF0, 0x10101010);
877198e6b0SRob Clark 		gpu_write(gpu, REG_A3XX_VBIF_OUT_WR_LIM_CONF0, 0x10101010);
887198e6b0SRob Clark 		gpu_write(gpu, REG_A3XX_VBIF_DDR_OUT_MAX_BURST, 0x0000303);
897198e6b0SRob Clark 		gpu_write(gpu, REG_A3XX_VBIF_IN_WR_LIM_CONF0, 0x10101010);
907198e6b0SRob Clark 		gpu_write(gpu, REG_A3XX_VBIF_IN_WR_LIM_CONF1, 0x10101010);
917198e6b0SRob Clark 		/* Enable WR-REQ: */
927198e6b0SRob Clark 		gpu_write(gpu, REG_A3XX_VBIF_GATE_OFF_WRREQ_EN, 0x0000ff);
937198e6b0SRob Clark 		/* Set up round robin arbitration between both AXI ports: */
947198e6b0SRob Clark 		gpu_write(gpu, REG_A3XX_VBIF_ARB_CTL, 0x00000030);
957198e6b0SRob Clark 		/* Set up AOOO: */
967198e6b0SRob Clark 		gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO_EN, 0x0000003c);
977198e6b0SRob Clark 		gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO, 0x003c003c);
987198e6b0SRob Clark 
997198e6b0SRob Clark 	} else if (adreno_is_a320(adreno_gpu)) {
1007198e6b0SRob Clark 		/* Set up 16 deep read/write request queues: */
1017198e6b0SRob Clark 		gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF0, 0x10101010);
1027198e6b0SRob Clark 		gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF1, 0x10101010);
1037198e6b0SRob Clark 		gpu_write(gpu, REG_A3XX_VBIF_OUT_RD_LIM_CONF0, 0x10101010);
1047198e6b0SRob Clark 		gpu_write(gpu, REG_A3XX_VBIF_OUT_WR_LIM_CONF0, 0x10101010);
1057198e6b0SRob Clark 		gpu_write(gpu, REG_A3XX_VBIF_DDR_OUT_MAX_BURST, 0x0000303);
1067198e6b0SRob Clark 		gpu_write(gpu, REG_A3XX_VBIF_IN_WR_LIM_CONF0, 0x10101010);
1077198e6b0SRob Clark 		gpu_write(gpu, REG_A3XX_VBIF_IN_WR_LIM_CONF1, 0x10101010);
1087198e6b0SRob Clark 		/* Enable WR-REQ: */
1097198e6b0SRob Clark 		gpu_write(gpu, REG_A3XX_VBIF_GATE_OFF_WRREQ_EN, 0x0000ff);
1107198e6b0SRob Clark 		/* Set up round robin arbitration between both AXI ports: */
1117198e6b0SRob Clark 		gpu_write(gpu, REG_A3XX_VBIF_ARB_CTL, 0x00000030);
1127198e6b0SRob Clark 		/* Set up AOOO: */
1137198e6b0SRob Clark 		gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO_EN, 0x0000003c);
1147198e6b0SRob Clark 		gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO, 0x003c003c);
1157198e6b0SRob Clark 		/* Enable 1K sort: */
1167198e6b0SRob Clark 		gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT, 0x000000ff);
1177198e6b0SRob Clark 		gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT_CONF, 0x000000a4);
1187198e6b0SRob Clark 
11955459968SRob Clark 	} else if (adreno_is_a330v2(adreno_gpu)) {
12055459968SRob Clark 		/*
12155459968SRob Clark 		 * Most of the VBIF registers on 8974v2 have the correct
12255459968SRob Clark 		 * values at power on, so we won't modify those if we don't
12355459968SRob Clark 		 * need to
12455459968SRob Clark 		 */
12555459968SRob Clark 		/* Enable 1k sort: */
12655459968SRob Clark 		gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT, 0x0001003f);
12755459968SRob Clark 		gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT_CONF, 0x000000a4);
12855459968SRob Clark 		/* Enable WR-REQ: */
12955459968SRob Clark 		gpu_write(gpu, REG_A3XX_VBIF_GATE_OFF_WRREQ_EN, 0x00003f);
13055459968SRob Clark 		gpu_write(gpu, REG_A3XX_VBIF_DDR_OUT_MAX_BURST, 0x0000303);
13155459968SRob Clark 		/* Set up VBIF_ROUND_ROBIN_QOS_ARB: */
13255459968SRob Clark 		gpu_write(gpu, REG_A3XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x0003);
13355459968SRob Clark 
1347198e6b0SRob Clark 	} else if (adreno_is_a330(adreno_gpu)) {
1357198e6b0SRob Clark 		/* Set up 16 deep read/write request queues: */
1367198e6b0SRob Clark 		gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF0, 0x18181818);
1377198e6b0SRob Clark 		gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF1, 0x18181818);
1387198e6b0SRob Clark 		gpu_write(gpu, REG_A3XX_VBIF_OUT_RD_LIM_CONF0, 0x18181818);
1397198e6b0SRob Clark 		gpu_write(gpu, REG_A3XX_VBIF_OUT_WR_LIM_CONF0, 0x18181818);
1407198e6b0SRob Clark 		gpu_write(gpu, REG_A3XX_VBIF_DDR_OUT_MAX_BURST, 0x0000303);
1417198e6b0SRob Clark 		gpu_write(gpu, REG_A3XX_VBIF_IN_WR_LIM_CONF0, 0x18181818);
1427198e6b0SRob Clark 		gpu_write(gpu, REG_A3XX_VBIF_IN_WR_LIM_CONF1, 0x18181818);
1437198e6b0SRob Clark 		/* Enable WR-REQ: */
1447198e6b0SRob Clark 		gpu_write(gpu, REG_A3XX_VBIF_GATE_OFF_WRREQ_EN, 0x00003f);
1457198e6b0SRob Clark 		/* Set up round robin arbitration between both AXI ports: */
1467198e6b0SRob Clark 		gpu_write(gpu, REG_A3XX_VBIF_ARB_CTL, 0x00000030);
1477198e6b0SRob Clark 		/* Set up VBIF_ROUND_ROBIN_QOS_ARB: */
1487198e6b0SRob Clark 		gpu_write(gpu, REG_A3XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x0001);
1497198e6b0SRob Clark 		/* Set up AOOO: */
15055459968SRob Clark 		gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO_EN, 0x0000003f);
15155459968SRob Clark 		gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO, 0x003f003f);
1527198e6b0SRob Clark 		/* Enable 1K sort: */
15355459968SRob Clark 		gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT, 0x0001003f);
1547198e6b0SRob Clark 		gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT_CONF, 0x000000a4);
1557198e6b0SRob Clark 		/* Disable VBIF clock gating. This is to enable AXI running
1567198e6b0SRob Clark 		 * higher frequency than GPU:
1577198e6b0SRob Clark 		 */
1587198e6b0SRob Clark 		gpu_write(gpu, REG_A3XX_VBIF_CLKON, 0x00000001);
1597198e6b0SRob Clark 
1607198e6b0SRob Clark 	} else {
1617198e6b0SRob Clark 		BUG();
1627198e6b0SRob Clark 	}
1637198e6b0SRob Clark 
1647198e6b0SRob Clark 	/* Make all blocks contribute to the GPU BUSY perf counter: */
1657198e6b0SRob Clark 	gpu_write(gpu, REG_A3XX_RBBM_GPU_BUSY_MASKED, 0xffffffff);
1667198e6b0SRob Clark 
1677198e6b0SRob Clark 	/* Tune the hystersis counters for SP and CP idle detection: */
1687198e6b0SRob Clark 	gpu_write(gpu, REG_A3XX_RBBM_SP_HYST_CNT, 0x10);
1697198e6b0SRob Clark 	gpu_write(gpu, REG_A3XX_RBBM_WAIT_IDLE_CLOCKS_CTL, 0x10);
1707198e6b0SRob Clark 
1717198e6b0SRob Clark 	/* Enable the RBBM error reporting bits.  This lets us get
1727198e6b0SRob Clark 	 * useful information on failure:
1737198e6b0SRob Clark 	 */
1747198e6b0SRob Clark 	gpu_write(gpu, REG_A3XX_RBBM_AHB_CTL0, 0x00000001);
1757198e6b0SRob Clark 
1767198e6b0SRob Clark 	/* Enable AHB error reporting: */
1777198e6b0SRob Clark 	gpu_write(gpu, REG_A3XX_RBBM_AHB_CTL1, 0xa6ffffff);
1787198e6b0SRob Clark 
1797198e6b0SRob Clark 	/* Turn on the power counters: */
1807198e6b0SRob Clark 	gpu_write(gpu, REG_A3XX_RBBM_RBBM_CTL, 0x00030000);
1817198e6b0SRob Clark 
1827198e6b0SRob Clark 	/* Turn on hang detection - this spews a lot of useful information
1837198e6b0SRob Clark 	 * into the RBBM registers on a hang:
1847198e6b0SRob Clark 	 */
1857198e6b0SRob Clark 	gpu_write(gpu, REG_A3XX_RBBM_INTERFACE_HANG_INT_CTL, 0x00010fff);
1867198e6b0SRob Clark 
1877198e6b0SRob Clark 	/* Enable 64-byte cacheline size. HW Default is 32-byte (0x000000E0): */
1887198e6b0SRob Clark 	gpu_write(gpu, REG_A3XX_UCHE_CACHE_MODE_CONTROL_REG, 0x00000001);
1897198e6b0SRob Clark 
1907198e6b0SRob Clark 	/* Enable Clock gating: */
19155459968SRob Clark 	if (adreno_is_a320(adreno_gpu))
1927198e6b0SRob Clark 		gpu_write(gpu, REG_A3XX_RBBM_CLOCK_CTL, 0xbfffffff);
19355459968SRob Clark 	else if (adreno_is_a330v2(adreno_gpu))
19455459968SRob Clark 		gpu_write(gpu, REG_A3XX_RBBM_CLOCK_CTL, 0xaaaaaaaa);
19555459968SRob Clark 	else if (adreno_is_a330(adreno_gpu))
19655459968SRob Clark 		gpu_write(gpu, REG_A3XX_RBBM_CLOCK_CTL, 0xbffcffff);
1977198e6b0SRob Clark 
19855459968SRob Clark 	if (adreno_is_a330v2(adreno_gpu))
19955459968SRob Clark 		gpu_write(gpu, REG_A3XX_RBBM_GPR0_CTL, 0x05515455);
20055459968SRob Clark 	else if (adreno_is_a330(adreno_gpu))
20155459968SRob Clark 		gpu_write(gpu, REG_A3XX_RBBM_GPR0_CTL, 0x00000000);
20255459968SRob Clark 
20355459968SRob Clark 	/* Set the OCMEM base address for A330, etc */
20455459968SRob Clark 	if (a3xx_gpu->ocmem_hdl) {
20555459968SRob Clark 		gpu_write(gpu, REG_A3XX_RB_GMEM_BASE_ADDR,
20655459968SRob Clark 			(unsigned int)(a3xx_gpu->ocmem_base >> 14));
20755459968SRob Clark 	}
2087198e6b0SRob Clark 
2097198e6b0SRob Clark 	/* Turn on performance counters: */
2107198e6b0SRob Clark 	gpu_write(gpu, REG_A3XX_RBBM_PERFCTR_CTL, 0x01);
2117198e6b0SRob Clark 
2127198e6b0SRob Clark 	/* Set SP perfcounter 7 to count SP_FS_FULL_ALU_INSTRUCTIONS
2137198e6b0SRob Clark 	 * we will use this to augment our hang detection:
2147198e6b0SRob Clark 	 */
2157198e6b0SRob Clark 	gpu_write(gpu, REG_A3XX_SP_PERFCOUNTER7_SELECT,
2167198e6b0SRob Clark 			SP_FS_FULL_ALU_INSTRUCTIONS);
2177198e6b0SRob Clark 
2187198e6b0SRob Clark 	gpu_write(gpu, REG_A3XX_RBBM_INT_0_MASK, A3XX_INT0_MASK);
2197198e6b0SRob Clark 
2207198e6b0SRob Clark 	ret = adreno_hw_init(gpu);
2217198e6b0SRob Clark 	if (ret)
2227198e6b0SRob Clark 		return ret;
2237198e6b0SRob Clark 
2247198e6b0SRob Clark 	/* setup access protection: */
2257198e6b0SRob Clark 	gpu_write(gpu, REG_A3XX_CP_PROTECT_CTRL, 0x00000007);
2267198e6b0SRob Clark 
2277198e6b0SRob Clark 	/* RBBM registers */
2287198e6b0SRob Clark 	gpu_write(gpu, REG_A3XX_CP_PROTECT(0), 0x63000040);
2297198e6b0SRob Clark 	gpu_write(gpu, REG_A3XX_CP_PROTECT(1), 0x62000080);
2307198e6b0SRob Clark 	gpu_write(gpu, REG_A3XX_CP_PROTECT(2), 0x600000cc);
2317198e6b0SRob Clark 	gpu_write(gpu, REG_A3XX_CP_PROTECT(3), 0x60000108);
2327198e6b0SRob Clark 	gpu_write(gpu, REG_A3XX_CP_PROTECT(4), 0x64000140);
2337198e6b0SRob Clark 	gpu_write(gpu, REG_A3XX_CP_PROTECT(5), 0x66000400);
2347198e6b0SRob Clark 
2357198e6b0SRob Clark 	/* CP registers */
2367198e6b0SRob Clark 	gpu_write(gpu, REG_A3XX_CP_PROTECT(6), 0x65000700);
2377198e6b0SRob Clark 	gpu_write(gpu, REG_A3XX_CP_PROTECT(7), 0x610007d8);
2387198e6b0SRob Clark 	gpu_write(gpu, REG_A3XX_CP_PROTECT(8), 0x620007e0);
2397198e6b0SRob Clark 	gpu_write(gpu, REG_A3XX_CP_PROTECT(9), 0x61001178);
2407198e6b0SRob Clark 	gpu_write(gpu, REG_A3XX_CP_PROTECT(10), 0x64001180);
2417198e6b0SRob Clark 
2427198e6b0SRob Clark 	/* RB registers */
2437198e6b0SRob Clark 	gpu_write(gpu, REG_A3XX_CP_PROTECT(11), 0x60003300);
2447198e6b0SRob Clark 
2457198e6b0SRob Clark 	/* VBIF registers */
2467198e6b0SRob Clark 	gpu_write(gpu, REG_A3XX_CP_PROTECT(12), 0x6b00c000);
2477198e6b0SRob Clark 
2487198e6b0SRob Clark 	/* NOTE: PM4/micro-engine firmware registers look to be the same
2497198e6b0SRob Clark 	 * for a2xx and a3xx.. we could possibly push that part down to
2507198e6b0SRob Clark 	 * adreno_gpu base class.  Or push both PM4 and PFP but
2517198e6b0SRob Clark 	 * parameterize the pfp ucode addr/data registers..
2527198e6b0SRob Clark 	 */
2537198e6b0SRob Clark 
2547198e6b0SRob Clark 	/* Load PM4: */
2557198e6b0SRob Clark 	ptr = (uint32_t *)(adreno_gpu->pm4->data);
2567198e6b0SRob Clark 	len = adreno_gpu->pm4->size / 4;
257e529c7e6SRob Clark 	DBG("loading PM4 ucode version: %x", ptr[1]);
2587198e6b0SRob Clark 
2597198e6b0SRob Clark 	gpu_write(gpu, REG_AXXX_CP_DEBUG,
2607198e6b0SRob Clark 			AXXX_CP_DEBUG_DYNAMIC_CLK_DISABLE |
2617198e6b0SRob Clark 			AXXX_CP_DEBUG_MIU_128BIT_WRITE_ENABLE);
2627198e6b0SRob Clark 	gpu_write(gpu, REG_AXXX_CP_ME_RAM_WADDR, 0);
2637198e6b0SRob Clark 	for (i = 1; i < len; i++)
2647198e6b0SRob Clark 		gpu_write(gpu, REG_AXXX_CP_ME_RAM_DATA, ptr[i]);
2657198e6b0SRob Clark 
2667198e6b0SRob Clark 	/* Load PFP: */
2677198e6b0SRob Clark 	ptr = (uint32_t *)(adreno_gpu->pfp->data);
2687198e6b0SRob Clark 	len = adreno_gpu->pfp->size / 4;
269e529c7e6SRob Clark 	DBG("loading PFP ucode version: %x", ptr[5]);
2707198e6b0SRob Clark 
2717198e6b0SRob Clark 	gpu_write(gpu, REG_A3XX_CP_PFP_UCODE_ADDR, 0);
2727198e6b0SRob Clark 	for (i = 1; i < len; i++)
2737198e6b0SRob Clark 		gpu_write(gpu, REG_A3XX_CP_PFP_UCODE_DATA, ptr[i]);
2747198e6b0SRob Clark 
2757198e6b0SRob Clark 	/* CP ROQ queue sizes (bytes) - RB:16, ST:16, IB1:32, IB2:64 */
27655459968SRob Clark 	if (adreno_is_a305(adreno_gpu) || adreno_is_a320(adreno_gpu)) {
2777198e6b0SRob Clark 		gpu_write(gpu, REG_AXXX_CP_QUEUE_THRESHOLDS,
2787198e6b0SRob Clark 				AXXX_CP_QUEUE_THRESHOLDS_CSQ_IB1_START(2) |
2797198e6b0SRob Clark 				AXXX_CP_QUEUE_THRESHOLDS_CSQ_IB2_START(6) |
2807198e6b0SRob Clark 				AXXX_CP_QUEUE_THRESHOLDS_CSQ_ST_START(14));
28155459968SRob Clark 	} else if (adreno_is_a330(adreno_gpu)) {
28255459968SRob Clark 		/* NOTE: this (value take from downstream android driver)
28355459968SRob Clark 		 * includes some bits outside of the known bitfields.  But
28455459968SRob Clark 		 * A330 has this "MERCIU queue" thing too, which might
28555459968SRob Clark 		 * explain a new bitfield or reshuffling:
28655459968SRob Clark 		 */
28755459968SRob Clark 		gpu_write(gpu, REG_AXXX_CP_QUEUE_THRESHOLDS, 0x003e2008);
28855459968SRob Clark 	}
2897198e6b0SRob Clark 
2907198e6b0SRob Clark 	/* clear ME_HALT to start micro engine */
2917198e6b0SRob Clark 	gpu_write(gpu, REG_AXXX_CP_ME_CNTL, 0);
2927198e6b0SRob Clark 
2937198e6b0SRob Clark 	a3xx_me_init(gpu);
2947198e6b0SRob Clark 
2957198e6b0SRob Clark 	return 0;
2967198e6b0SRob Clark }
2977198e6b0SRob Clark 
29855459968SRob Clark static void a3xx_recover(struct msm_gpu *gpu)
29955459968SRob Clark {
3005b6ef08eSRob Clark 	/* dump registers before resetting gpu, if enabled: */
3015b6ef08eSRob Clark 	if (hang_debug)
3025b6ef08eSRob Clark 		a3xx_dump(gpu);
30355459968SRob Clark 	gpu_write(gpu, REG_A3XX_RBBM_SW_RESET_CMD, 1);
30455459968SRob Clark 	gpu_read(gpu, REG_A3XX_RBBM_SW_RESET_CMD);
30555459968SRob Clark 	gpu_write(gpu, REG_A3XX_RBBM_SW_RESET_CMD, 0);
30655459968SRob Clark 	adreno_recover(gpu);
30755459968SRob Clark }
30855459968SRob Clark 
3097198e6b0SRob Clark static void a3xx_destroy(struct msm_gpu *gpu)
3107198e6b0SRob Clark {
3117198e6b0SRob Clark 	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
3127198e6b0SRob Clark 	struct a3xx_gpu *a3xx_gpu = to_a3xx_gpu(adreno_gpu);
3137198e6b0SRob Clark 
3147198e6b0SRob Clark 	DBG("%s", gpu->name);
3157198e6b0SRob Clark 
3167198e6b0SRob Clark 	adreno_gpu_cleanup(adreno_gpu);
31755459968SRob Clark 
31855459968SRob Clark #ifdef CONFIG_MSM_OCMEM
31955459968SRob Clark 	if (a3xx_gpu->ocmem_base)
32055459968SRob Clark 		ocmem_free(OCMEM_GRAPHICS, a3xx_gpu->ocmem_hdl);
32155459968SRob Clark #endif
32255459968SRob Clark 
3237198e6b0SRob Clark 	put_device(&a3xx_gpu->pdev->dev);
3247198e6b0SRob Clark 	kfree(a3xx_gpu);
3257198e6b0SRob Clark }
3267198e6b0SRob Clark 
3277198e6b0SRob Clark static void a3xx_idle(struct msm_gpu *gpu)
3287198e6b0SRob Clark {
3297198e6b0SRob Clark 	/* wait for ringbuffer to drain: */
3307198e6b0SRob Clark 	adreno_idle(gpu);
3317198e6b0SRob Clark 
3327198e6b0SRob Clark 	/* then wait for GPU to finish: */
333*0963756fSRob Clark 	if (spin_until(!(gpu_read(gpu, REG_A3XX_RBBM_STATUS) &
334*0963756fSRob Clark 			A3XX_RBBM_STATUS_GPU_BUSY)))
335*0963756fSRob Clark 		DRM_ERROR("%s: timeout waiting for GPU to idle!\n", gpu->name);
3367198e6b0SRob Clark 
3377198e6b0SRob Clark 	/* TODO maybe we need to reset GPU here to recover from hang? */
3387198e6b0SRob Clark }
3397198e6b0SRob Clark 
3407198e6b0SRob Clark static irqreturn_t a3xx_irq(struct msm_gpu *gpu)
3417198e6b0SRob Clark {
3427198e6b0SRob Clark 	uint32_t status;
3437198e6b0SRob Clark 
3447198e6b0SRob Clark 	status = gpu_read(gpu, REG_A3XX_RBBM_INT_0_STATUS);
3457198e6b0SRob Clark 	DBG("%s: %08x", gpu->name, status);
3467198e6b0SRob Clark 
3477198e6b0SRob Clark 	// TODO
3487198e6b0SRob Clark 
3497198e6b0SRob Clark 	gpu_write(gpu, REG_A3XX_RBBM_INT_CLEAR_CMD, status);
3507198e6b0SRob Clark 
3517198e6b0SRob Clark 	msm_gpu_retire(gpu);
3527198e6b0SRob Clark 
3537198e6b0SRob Clark 	return IRQ_HANDLED;
3547198e6b0SRob Clark }
3557198e6b0SRob Clark 
3567198e6b0SRob Clark static const unsigned int a3xx_registers[] = {
3577198e6b0SRob Clark 	0x0000, 0x0002, 0x0010, 0x0012, 0x0018, 0x0018, 0x0020, 0x0027,
3587198e6b0SRob Clark 	0x0029, 0x002b, 0x002e, 0x0033, 0x0040, 0x0042, 0x0050, 0x005c,
3597198e6b0SRob Clark 	0x0060, 0x006c, 0x0080, 0x0082, 0x0084, 0x0088, 0x0090, 0x00e5,
3607198e6b0SRob Clark 	0x00ea, 0x00ed, 0x0100, 0x0100, 0x0110, 0x0123, 0x01c0, 0x01c1,
3617198e6b0SRob Clark 	0x01c3, 0x01c5, 0x01c7, 0x01c7, 0x01d5, 0x01d9, 0x01dc, 0x01dd,
3627198e6b0SRob Clark 	0x01ea, 0x01ea, 0x01ee, 0x01f1, 0x01f5, 0x01f5, 0x01fc, 0x01ff,
3637198e6b0SRob Clark 	0x0440, 0x0440, 0x0443, 0x0443, 0x0445, 0x0445, 0x044d, 0x044f,
3647198e6b0SRob Clark 	0x0452, 0x0452, 0x0454, 0x046f, 0x047c, 0x047c, 0x047f, 0x047f,
3657198e6b0SRob Clark 	0x0578, 0x057f, 0x0600, 0x0602, 0x0605, 0x0607, 0x060a, 0x060e,
3667198e6b0SRob Clark 	0x0612, 0x0614, 0x0c01, 0x0c02, 0x0c06, 0x0c1d, 0x0c3d, 0x0c3f,
3677198e6b0SRob Clark 	0x0c48, 0x0c4b, 0x0c80, 0x0c80, 0x0c88, 0x0c8b, 0x0ca0, 0x0cb7,
3687198e6b0SRob Clark 	0x0cc0, 0x0cc1, 0x0cc6, 0x0cc7, 0x0ce4, 0x0ce5, 0x0e00, 0x0e05,
3697198e6b0SRob Clark 	0x0e0c, 0x0e0c, 0x0e22, 0x0e23, 0x0e41, 0x0e45, 0x0e64, 0x0e65,
3707198e6b0SRob Clark 	0x0e80, 0x0e82, 0x0e84, 0x0e89, 0x0ea0, 0x0ea1, 0x0ea4, 0x0ea7,
3717198e6b0SRob Clark 	0x0ec4, 0x0ecb, 0x0ee0, 0x0ee0, 0x0f00, 0x0f01, 0x0f03, 0x0f09,
3727198e6b0SRob Clark 	0x2040, 0x2040, 0x2044, 0x2044, 0x2048, 0x204d, 0x2068, 0x2069,
3737198e6b0SRob Clark 	0x206c, 0x206d, 0x2070, 0x2070, 0x2072, 0x2072, 0x2074, 0x2075,
3747198e6b0SRob Clark 	0x2079, 0x207a, 0x20c0, 0x20d3, 0x20e4, 0x20ef, 0x2100, 0x2109,
3757198e6b0SRob Clark 	0x210c, 0x210c, 0x210e, 0x210e, 0x2110, 0x2111, 0x2114, 0x2115,
3767198e6b0SRob Clark 	0x21e4, 0x21e4, 0x21ea, 0x21ea, 0x21ec, 0x21ed, 0x21f0, 0x21f0,
3777198e6b0SRob Clark 	0x2200, 0x2212, 0x2214, 0x2217, 0x221a, 0x221a, 0x2240, 0x227e,
3787198e6b0SRob Clark 	0x2280, 0x228b, 0x22c0, 0x22c0, 0x22c4, 0x22ce, 0x22d0, 0x22d8,
3797198e6b0SRob Clark 	0x22df, 0x22e6, 0x22e8, 0x22e9, 0x22ec, 0x22ec, 0x22f0, 0x22f7,
3807198e6b0SRob Clark 	0x22ff, 0x22ff, 0x2340, 0x2343, 0x2348, 0x2349, 0x2350, 0x2356,
3817198e6b0SRob Clark 	0x2360, 0x2360, 0x2440, 0x2440, 0x2444, 0x2444, 0x2448, 0x244d,
3827198e6b0SRob Clark 	0x2468, 0x2469, 0x246c, 0x246d, 0x2470, 0x2470, 0x2472, 0x2472,
3837198e6b0SRob Clark 	0x2474, 0x2475, 0x2479, 0x247a, 0x24c0, 0x24d3, 0x24e4, 0x24ef,
3847198e6b0SRob Clark 	0x2500, 0x2509, 0x250c, 0x250c, 0x250e, 0x250e, 0x2510, 0x2511,
3857198e6b0SRob Clark 	0x2514, 0x2515, 0x25e4, 0x25e4, 0x25ea, 0x25ea, 0x25ec, 0x25ed,
3867198e6b0SRob Clark 	0x25f0, 0x25f0, 0x2600, 0x2612, 0x2614, 0x2617, 0x261a, 0x261a,
3877198e6b0SRob Clark 	0x2640, 0x267e, 0x2680, 0x268b, 0x26c0, 0x26c0, 0x26c4, 0x26ce,
3887198e6b0SRob Clark 	0x26d0, 0x26d8, 0x26df, 0x26e6, 0x26e8, 0x26e9, 0x26ec, 0x26ec,
3897198e6b0SRob Clark 	0x26f0, 0x26f7, 0x26ff, 0x26ff, 0x2740, 0x2743, 0x2748, 0x2749,
3907198e6b0SRob Clark 	0x2750, 0x2756, 0x2760, 0x2760, 0x300c, 0x300e, 0x301c, 0x301d,
3917198e6b0SRob Clark 	0x302a, 0x302a, 0x302c, 0x302d, 0x3030, 0x3031, 0x3034, 0x3036,
3927198e6b0SRob Clark 	0x303c, 0x303c, 0x305e, 0x305f,
3937198e6b0SRob Clark };
3947198e6b0SRob Clark 
3955b6ef08eSRob Clark #ifdef CONFIG_DEBUG_FS
3967198e6b0SRob Clark static void a3xx_show(struct msm_gpu *gpu, struct seq_file *m)
3977198e6b0SRob Clark {
3987198e6b0SRob Clark 	int i;
3997198e6b0SRob Clark 
4007198e6b0SRob Clark 	adreno_show(gpu, m);
4017198e6b0SRob Clark 	seq_printf(m, "status:   %08x\n",
4027198e6b0SRob Clark 			gpu_read(gpu, REG_A3XX_RBBM_STATUS));
4037198e6b0SRob Clark 
4047198e6b0SRob Clark 	/* dump these out in a form that can be parsed by demsm: */
4057198e6b0SRob Clark 	seq_printf(m, "IO:region %s 00000000 00020000\n", gpu->name);
4067198e6b0SRob Clark 	for (i = 0; i < ARRAY_SIZE(a3xx_registers); i += 2) {
4077198e6b0SRob Clark 		uint32_t start = a3xx_registers[i];
4087198e6b0SRob Clark 		uint32_t end   = a3xx_registers[i+1];
4097198e6b0SRob Clark 		uint32_t addr;
4107198e6b0SRob Clark 
4117198e6b0SRob Clark 		for (addr = start; addr <= end; addr++) {
4127198e6b0SRob Clark 			uint32_t val = gpu_read(gpu, addr);
4137198e6b0SRob Clark 			seq_printf(m, "IO:R %08x %08x\n", addr<<2, val);
4147198e6b0SRob Clark 		}
4157198e6b0SRob Clark 	}
4167198e6b0SRob Clark }
4177198e6b0SRob Clark #endif
4187198e6b0SRob Clark 
4195b6ef08eSRob Clark /* would be nice to not have to duplicate the _show() stuff with printk(): */
4205b6ef08eSRob Clark static void a3xx_dump(struct msm_gpu *gpu)
4215b6ef08eSRob Clark {
4225b6ef08eSRob Clark 	int i;
4235b6ef08eSRob Clark 
4245b6ef08eSRob Clark 	adreno_dump(gpu);
4255b6ef08eSRob Clark 	printk("status:   %08x\n",
4265b6ef08eSRob Clark 			gpu_read(gpu, REG_A3XX_RBBM_STATUS));
4275b6ef08eSRob Clark 
4285b6ef08eSRob Clark 	/* dump these out in a form that can be parsed by demsm: */
4295b6ef08eSRob Clark 	printk("IO:region %s 00000000 00020000\n", gpu->name);
4305b6ef08eSRob Clark 	for (i = 0; i < ARRAY_SIZE(a3xx_registers); i += 2) {
4315b6ef08eSRob Clark 		uint32_t start = a3xx_registers[i];
4325b6ef08eSRob Clark 		uint32_t end   = a3xx_registers[i+1];
4335b6ef08eSRob Clark 		uint32_t addr;
4345b6ef08eSRob Clark 
4355b6ef08eSRob Clark 		for (addr = start; addr <= end; addr++) {
4365b6ef08eSRob Clark 			uint32_t val = gpu_read(gpu, addr);
4375b6ef08eSRob Clark 			printk("IO:R %08x %08x\n", addr<<2, val);
4385b6ef08eSRob Clark 		}
4395b6ef08eSRob Clark 	}
4405b6ef08eSRob Clark }
4415b6ef08eSRob Clark 
4427198e6b0SRob Clark static const struct adreno_gpu_funcs funcs = {
4437198e6b0SRob Clark 	.base = {
4447198e6b0SRob Clark 		.get_param = adreno_get_param,
4457198e6b0SRob Clark 		.hw_init = a3xx_hw_init,
4467198e6b0SRob Clark 		.pm_suspend = msm_gpu_pm_suspend,
4477198e6b0SRob Clark 		.pm_resume = msm_gpu_pm_resume,
44855459968SRob Clark 		.recover = a3xx_recover,
4497198e6b0SRob Clark 		.last_fence = adreno_last_fence,
4507198e6b0SRob Clark 		.submit = adreno_submit,
4517198e6b0SRob Clark 		.flush = adreno_flush,
4527198e6b0SRob Clark 		.idle = a3xx_idle,
4537198e6b0SRob Clark 		.irq = a3xx_irq,
4547198e6b0SRob Clark 		.destroy = a3xx_destroy,
4557198e6b0SRob Clark #ifdef CONFIG_DEBUG_FS
4567198e6b0SRob Clark 		.show = a3xx_show,
4577198e6b0SRob Clark #endif
4587198e6b0SRob Clark 	},
4597198e6b0SRob Clark };
4607198e6b0SRob Clark 
4617198e6b0SRob Clark struct msm_gpu *a3xx_gpu_init(struct drm_device *dev)
4627198e6b0SRob Clark {
4637198e6b0SRob Clark 	struct a3xx_gpu *a3xx_gpu = NULL;
46455459968SRob Clark 	struct adreno_gpu *adreno_gpu;
4657198e6b0SRob Clark 	struct msm_gpu *gpu;
4667198e6b0SRob Clark 	struct platform_device *pdev = a3xx_pdev;
4677198e6b0SRob Clark 	struct adreno_platform_config *config;
4687198e6b0SRob Clark 	int ret;
4697198e6b0SRob Clark 
4707198e6b0SRob Clark 	if (!pdev) {
4717198e6b0SRob Clark 		dev_err(dev->dev, "no a3xx device\n");
4727198e6b0SRob Clark 		ret = -ENXIO;
4737198e6b0SRob Clark 		goto fail;
4747198e6b0SRob Clark 	}
4757198e6b0SRob Clark 
4767198e6b0SRob Clark 	config = pdev->dev.platform_data;
4777198e6b0SRob Clark 
4787198e6b0SRob Clark 	a3xx_gpu = kzalloc(sizeof(*a3xx_gpu), GFP_KERNEL);
4797198e6b0SRob Clark 	if (!a3xx_gpu) {
4807198e6b0SRob Clark 		ret = -ENOMEM;
4817198e6b0SRob Clark 		goto fail;
4827198e6b0SRob Clark 	}
4837198e6b0SRob Clark 
48455459968SRob Clark 	adreno_gpu = &a3xx_gpu->base;
48555459968SRob Clark 	gpu = &adreno_gpu->base;
4867198e6b0SRob Clark 
4877198e6b0SRob Clark 	get_device(&pdev->dev);
4887198e6b0SRob Clark 	a3xx_gpu->pdev = pdev;
4897198e6b0SRob Clark 
4907198e6b0SRob Clark 	gpu->fast_rate = config->fast_rate;
4917198e6b0SRob Clark 	gpu->slow_rate = config->slow_rate;
4927198e6b0SRob Clark 	gpu->bus_freq  = config->bus_freq;
493bf2b33afSRob Clark #ifdef CONFIG_MSM_BUS_SCALING
494bf2b33afSRob Clark 	gpu->bus_scale_table = config->bus_scale_table;
495bf2b33afSRob Clark #endif
4967198e6b0SRob Clark 
4977198e6b0SRob Clark 	DBG("fast_rate=%u, slow_rate=%u, bus_freq=%u",
4987198e6b0SRob Clark 			gpu->fast_rate, gpu->slow_rate, gpu->bus_freq);
4997198e6b0SRob Clark 
50055459968SRob Clark 	ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, config->rev);
5017198e6b0SRob Clark 	if (ret)
5027198e6b0SRob Clark 		goto fail;
5037198e6b0SRob Clark 
50455459968SRob Clark 	/* if needed, allocate gmem: */
50555459968SRob Clark 	if (adreno_is_a330(adreno_gpu)) {
50655459968SRob Clark #ifdef CONFIG_MSM_OCMEM
50755459968SRob Clark 		/* TODO this is different/missing upstream: */
50855459968SRob Clark 		struct ocmem_buf *ocmem_hdl =
50955459968SRob Clark 				ocmem_allocate(OCMEM_GRAPHICS, adreno_gpu->gmem);
51055459968SRob Clark 
51155459968SRob Clark 		a3xx_gpu->ocmem_hdl = ocmem_hdl;
51255459968SRob Clark 		a3xx_gpu->ocmem_base = ocmem_hdl->addr;
51355459968SRob Clark 		adreno_gpu->gmem = ocmem_hdl->len;
51455459968SRob Clark 		DBG("using %dK of OCMEM at 0x%08x", adreno_gpu->gmem / 1024,
51555459968SRob Clark 				a3xx_gpu->ocmem_base);
51655459968SRob Clark #endif
51755459968SRob Clark 	}
51855459968SRob Clark 
519871d812aSRob Clark 	if (!gpu->mmu) {
520871d812aSRob Clark 		/* TODO we think it is possible to configure the GPU to
521871d812aSRob Clark 		 * restrict access to VRAM carveout.  But the required
522871d812aSRob Clark 		 * registers are unknown.  For now just bail out and
523871d812aSRob Clark 		 * limp along with just modesetting.  If it turns out
524871d812aSRob Clark 		 * to not be possible to restrict access, then we must
525871d812aSRob Clark 		 * implement a cmdstream validator.
526871d812aSRob Clark 		 */
527871d812aSRob Clark 		dev_err(dev->dev, "No memory protection without IOMMU\n");
528871d812aSRob Clark 		ret = -ENXIO;
529871d812aSRob Clark 		goto fail;
530871d812aSRob Clark 	}
531871d812aSRob Clark 
532871d812aSRob Clark 	return gpu;
5337198e6b0SRob Clark 
5347198e6b0SRob Clark fail:
5357198e6b0SRob Clark 	if (a3xx_gpu)
5367198e6b0SRob Clark 		a3xx_destroy(&a3xx_gpu->base.base);
5377198e6b0SRob Clark 
5387198e6b0SRob Clark 	return ERR_PTR(ret);
5397198e6b0SRob Clark }
5407198e6b0SRob Clark 
5417198e6b0SRob Clark /*
5427198e6b0SRob Clark  * The a3xx device:
5437198e6b0SRob Clark  */
5447198e6b0SRob Clark 
545bf2b33afSRob Clark #if defined(CONFIG_MSM_BUS_SCALING) && !defined(CONFIG_OF)
546bf2b33afSRob Clark #  include <mach/kgsl.h>
547bf2b33afSRob Clark #endif
548bf2b33afSRob Clark 
5497198e6b0SRob Clark static int a3xx_probe(struct platform_device *pdev)
5507198e6b0SRob Clark {
5517198e6b0SRob Clark 	static struct adreno_platform_config config = {};
5527198e6b0SRob Clark #ifdef CONFIG_OF
55355459968SRob Clark 	struct device_node *child, *node = pdev->dev.of_node;
55455459968SRob Clark 	u32 val;
55555459968SRob Clark 	int ret;
55655459968SRob Clark 
55755459968SRob Clark 	ret = of_property_read_u32(node, "qcom,chipid", &val);
55855459968SRob Clark 	if (ret) {
55955459968SRob Clark 		dev_err(&pdev->dev, "could not find chipid: %d\n", ret);
56055459968SRob Clark 		return ret;
56155459968SRob Clark 	}
56255459968SRob Clark 
56355459968SRob Clark 	config.rev = ADRENO_REV((val >> 24) & 0xff,
56455459968SRob Clark 			(val >> 16) & 0xff, (val >> 8) & 0xff, val & 0xff);
56555459968SRob Clark 
56655459968SRob Clark 	/* find clock rates: */
56755459968SRob Clark 	config.fast_rate = 0;
56855459968SRob Clark 	config.slow_rate = ~0;
56955459968SRob Clark 	for_each_child_of_node(node, child) {
57055459968SRob Clark 		if (of_device_is_compatible(child, "qcom,gpu-pwrlevels")) {
57155459968SRob Clark 			struct device_node *pwrlvl;
57255459968SRob Clark 			for_each_child_of_node(child, pwrlvl) {
57355459968SRob Clark 				ret = of_property_read_u32(pwrlvl, "qcom,gpu-freq", &val);
57455459968SRob Clark 				if (ret) {
57555459968SRob Clark 					dev_err(&pdev->dev, "could not find gpu-freq: %d\n", ret);
57655459968SRob Clark 					return ret;
57755459968SRob Clark 				}
57855459968SRob Clark 				config.fast_rate = max(config.fast_rate, val);
57955459968SRob Clark 				config.slow_rate = min(config.slow_rate, val);
58055459968SRob Clark 			}
58155459968SRob Clark 		}
58255459968SRob Clark 	}
58355459968SRob Clark 
58455459968SRob Clark 	if (!config.fast_rate) {
58555459968SRob Clark 		dev_err(&pdev->dev, "could not find clk rates\n");
58655459968SRob Clark 		return -ENXIO;
58755459968SRob Clark 	}
58855459968SRob Clark 
5897198e6b0SRob Clark #else
590bf2b33afSRob Clark 	struct kgsl_device_platform_data *pdata = pdev->dev.platform_data;
5917198e6b0SRob Clark 	uint32_t version = socinfo_get_version();
5927198e6b0SRob Clark 	if (cpu_is_apq8064ab()) {
5937198e6b0SRob Clark 		config.fast_rate = 450000000;
5947198e6b0SRob Clark 		config.slow_rate = 27000000;
5957198e6b0SRob Clark 		config.bus_freq  = 4;
5967198e6b0SRob Clark 		config.rev = ADRENO_REV(3, 2, 1, 0);
597e529c7e6SRob Clark 	} else if (cpu_is_apq8064()) {
5987198e6b0SRob Clark 		config.fast_rate = 400000000;
5997198e6b0SRob Clark 		config.slow_rate = 27000000;
6007198e6b0SRob Clark 		config.bus_freq  = 4;
6017198e6b0SRob Clark 
6027198e6b0SRob Clark 		if (SOCINFO_VERSION_MAJOR(version) == 2)
6037198e6b0SRob Clark 			config.rev = ADRENO_REV(3, 2, 0, 2);
6047198e6b0SRob Clark 		else if ((SOCINFO_VERSION_MAJOR(version) == 1) &&
6057198e6b0SRob Clark 				(SOCINFO_VERSION_MINOR(version) == 1))
6067198e6b0SRob Clark 			config.rev = ADRENO_REV(3, 2, 0, 1);
6077198e6b0SRob Clark 		else
6087198e6b0SRob Clark 			config.rev = ADRENO_REV(3, 2, 0, 0);
6097198e6b0SRob Clark 
610e529c7e6SRob Clark 	} else if (cpu_is_msm8960ab()) {
611e529c7e6SRob Clark 		config.fast_rate = 400000000;
612e529c7e6SRob Clark 		config.slow_rate = 320000000;
613e529c7e6SRob Clark 		config.bus_freq  = 4;
614e529c7e6SRob Clark 
615e529c7e6SRob Clark 		if (SOCINFO_VERSION_MINOR(version) == 0)
616e529c7e6SRob Clark 			config.rev = ADRENO_REV(3, 2, 1, 0);
617e529c7e6SRob Clark 		else
618e529c7e6SRob Clark 			config.rev = ADRENO_REV(3, 2, 1, 1);
619e529c7e6SRob Clark 
6207198e6b0SRob Clark 	} else if (cpu_is_msm8930()) {
6217198e6b0SRob Clark 		config.fast_rate = 400000000;
6227198e6b0SRob Clark 		config.slow_rate = 27000000;
6237198e6b0SRob Clark 		config.bus_freq  = 3;
6247198e6b0SRob Clark 
6257198e6b0SRob Clark 		if ((SOCINFO_VERSION_MAJOR(version) == 1) &&
6267198e6b0SRob Clark 			(SOCINFO_VERSION_MINOR(version) == 2))
6277198e6b0SRob Clark 			config.rev = ADRENO_REV(3, 0, 5, 2);
6287198e6b0SRob Clark 		else
6297198e6b0SRob Clark 			config.rev = ADRENO_REV(3, 0, 5, 0);
6307198e6b0SRob Clark 
6317198e6b0SRob Clark 	}
632bf2b33afSRob Clark #  ifdef CONFIG_MSM_BUS_SCALING
633bf2b33afSRob Clark 	config.bus_scale_table = pdata->bus_scale_table;
634bf2b33afSRob Clark #  endif
6357198e6b0SRob Clark #endif
6367198e6b0SRob Clark 	pdev->dev.platform_data = &config;
6377198e6b0SRob Clark 	a3xx_pdev = pdev;
6387198e6b0SRob Clark 	return 0;
6397198e6b0SRob Clark }
6407198e6b0SRob Clark 
6417198e6b0SRob Clark static int a3xx_remove(struct platform_device *pdev)
6427198e6b0SRob Clark {
6437198e6b0SRob Clark 	a3xx_pdev = NULL;
6447198e6b0SRob Clark 	return 0;
6457198e6b0SRob Clark }
6467198e6b0SRob Clark 
64755459968SRob Clark static const struct of_device_id dt_match[] = {
64855459968SRob Clark 	{ .compatible = "qcom,kgsl-3d0" },
64955459968SRob Clark 	{}
65055459968SRob Clark };
65155459968SRob Clark MODULE_DEVICE_TABLE(of, dt_match);
65255459968SRob Clark 
6537198e6b0SRob Clark static struct platform_driver a3xx_driver = {
6547198e6b0SRob Clark 	.probe = a3xx_probe,
6557198e6b0SRob Clark 	.remove = a3xx_remove,
65655459968SRob Clark 	.driver = {
65755459968SRob Clark 		.name = "kgsl-3d0",
65855459968SRob Clark 		.of_match_table = dt_match,
65955459968SRob Clark 	},
6607198e6b0SRob Clark };
6617198e6b0SRob Clark 
6627198e6b0SRob Clark void __init a3xx_register(void)
6637198e6b0SRob Clark {
6647198e6b0SRob Clark 	platform_driver_register(&a3xx_driver);
6657198e6b0SRob Clark }
6667198e6b0SRob Clark 
6677198e6b0SRob Clark void __exit a3xx_unregister(void)
6687198e6b0SRob Clark {
6697198e6b0SRob Clark 	platform_driver_unregister(&a3xx_driver);
6707198e6b0SRob Clark }
671