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 void a3xx_me_init(struct msm_gpu *gpu) 457198e6b0SRob Clark { 467198e6b0SRob Clark struct msm_ringbuffer *ring = gpu->rb; 477198e6b0SRob Clark 487198e6b0SRob Clark OUT_PKT3(ring, CP_ME_INIT, 17); 497198e6b0SRob Clark OUT_RING(ring, 0x000003f7); 507198e6b0SRob Clark OUT_RING(ring, 0x00000000); 517198e6b0SRob Clark OUT_RING(ring, 0x00000000); 527198e6b0SRob Clark OUT_RING(ring, 0x00000000); 537198e6b0SRob Clark OUT_RING(ring, 0x00000080); 547198e6b0SRob Clark OUT_RING(ring, 0x00000100); 557198e6b0SRob Clark OUT_RING(ring, 0x00000180); 567198e6b0SRob Clark OUT_RING(ring, 0x00006600); 577198e6b0SRob Clark OUT_RING(ring, 0x00000150); 587198e6b0SRob Clark OUT_RING(ring, 0x0000014e); 597198e6b0SRob Clark OUT_RING(ring, 0x00000154); 607198e6b0SRob Clark OUT_RING(ring, 0x00000001); 617198e6b0SRob Clark OUT_RING(ring, 0x00000000); 627198e6b0SRob Clark OUT_RING(ring, 0x00000000); 637198e6b0SRob Clark OUT_RING(ring, 0x00000000); 647198e6b0SRob Clark OUT_RING(ring, 0x00000000); 657198e6b0SRob Clark OUT_RING(ring, 0x00000000); 667198e6b0SRob Clark 677198e6b0SRob Clark gpu->funcs->flush(gpu); 687198e6b0SRob Clark gpu->funcs->idle(gpu); 697198e6b0SRob Clark } 707198e6b0SRob Clark 717198e6b0SRob Clark static int a3xx_hw_init(struct msm_gpu *gpu) 727198e6b0SRob Clark { 737198e6b0SRob Clark struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 7455459968SRob Clark struct a3xx_gpu *a3xx_gpu = to_a3xx_gpu(adreno_gpu); 757198e6b0SRob Clark uint32_t *ptr, len; 767198e6b0SRob Clark int i, ret; 777198e6b0SRob Clark 787198e6b0SRob Clark DBG("%s", gpu->name); 797198e6b0SRob Clark 807198e6b0SRob Clark if (adreno_is_a305(adreno_gpu)) { 817198e6b0SRob Clark /* Set up 16 deep read/write request queues: */ 827198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF0, 0x10101010); 837198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF1, 0x10101010); 847198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_OUT_RD_LIM_CONF0, 0x10101010); 857198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_OUT_WR_LIM_CONF0, 0x10101010); 867198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_DDR_OUT_MAX_BURST, 0x0000303); 877198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_IN_WR_LIM_CONF0, 0x10101010); 887198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_IN_WR_LIM_CONF1, 0x10101010); 897198e6b0SRob Clark /* Enable WR-REQ: */ 907198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_GATE_OFF_WRREQ_EN, 0x0000ff); 917198e6b0SRob Clark /* Set up round robin arbitration between both AXI ports: */ 927198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_ARB_CTL, 0x00000030); 937198e6b0SRob Clark /* Set up AOOO: */ 947198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO_EN, 0x0000003c); 957198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO, 0x003c003c); 967198e6b0SRob Clark 977198e6b0SRob Clark } else if (adreno_is_a320(adreno_gpu)) { 987198e6b0SRob Clark /* Set up 16 deep read/write request queues: */ 997198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF0, 0x10101010); 1007198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF1, 0x10101010); 1017198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_OUT_RD_LIM_CONF0, 0x10101010); 1027198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_OUT_WR_LIM_CONF0, 0x10101010); 1037198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_DDR_OUT_MAX_BURST, 0x0000303); 1047198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_IN_WR_LIM_CONF0, 0x10101010); 1057198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_IN_WR_LIM_CONF1, 0x10101010); 1067198e6b0SRob Clark /* Enable WR-REQ: */ 1077198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_GATE_OFF_WRREQ_EN, 0x0000ff); 1087198e6b0SRob Clark /* Set up round robin arbitration between both AXI ports: */ 1097198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_ARB_CTL, 0x00000030); 1107198e6b0SRob Clark /* Set up AOOO: */ 1117198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO_EN, 0x0000003c); 1127198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO, 0x003c003c); 1137198e6b0SRob Clark /* Enable 1K sort: */ 1147198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT, 0x000000ff); 1157198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT_CONF, 0x000000a4); 1167198e6b0SRob Clark 11755459968SRob Clark } else if (adreno_is_a330v2(adreno_gpu)) { 11855459968SRob Clark /* 11955459968SRob Clark * Most of the VBIF registers on 8974v2 have the correct 12055459968SRob Clark * values at power on, so we won't modify those if we don't 12155459968SRob Clark * need to 12255459968SRob Clark */ 12355459968SRob Clark /* Enable 1k sort: */ 12455459968SRob Clark gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT, 0x0001003f); 12555459968SRob Clark gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT_CONF, 0x000000a4); 12655459968SRob Clark /* Enable WR-REQ: */ 12755459968SRob Clark gpu_write(gpu, REG_A3XX_VBIF_GATE_OFF_WRREQ_EN, 0x00003f); 12855459968SRob Clark gpu_write(gpu, REG_A3XX_VBIF_DDR_OUT_MAX_BURST, 0x0000303); 12955459968SRob Clark /* Set up VBIF_ROUND_ROBIN_QOS_ARB: */ 13055459968SRob Clark gpu_write(gpu, REG_A3XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x0003); 13155459968SRob Clark 1327198e6b0SRob Clark } else if (adreno_is_a330(adreno_gpu)) { 1337198e6b0SRob Clark /* Set up 16 deep read/write request queues: */ 1347198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF0, 0x18181818); 1357198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF1, 0x18181818); 1367198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_OUT_RD_LIM_CONF0, 0x18181818); 1377198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_OUT_WR_LIM_CONF0, 0x18181818); 1387198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_DDR_OUT_MAX_BURST, 0x0000303); 1397198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_IN_WR_LIM_CONF0, 0x18181818); 1407198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_IN_WR_LIM_CONF1, 0x18181818); 1417198e6b0SRob Clark /* Enable WR-REQ: */ 1427198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_GATE_OFF_WRREQ_EN, 0x00003f); 1437198e6b0SRob Clark /* Set up round robin arbitration between both AXI ports: */ 1447198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_ARB_CTL, 0x00000030); 1457198e6b0SRob Clark /* Set up VBIF_ROUND_ROBIN_QOS_ARB: */ 1467198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x0001); 1477198e6b0SRob Clark /* Set up AOOO: */ 14855459968SRob Clark gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO_EN, 0x0000003f); 14955459968SRob Clark gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO, 0x003f003f); 1507198e6b0SRob Clark /* Enable 1K sort: */ 15155459968SRob Clark gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT, 0x0001003f); 1527198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT_CONF, 0x000000a4); 1537198e6b0SRob Clark /* Disable VBIF clock gating. This is to enable AXI running 1547198e6b0SRob Clark * higher frequency than GPU: 1557198e6b0SRob Clark */ 1567198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_CLKON, 0x00000001); 1577198e6b0SRob Clark 1587198e6b0SRob Clark } else { 1597198e6b0SRob Clark BUG(); 1607198e6b0SRob Clark } 1617198e6b0SRob Clark 1627198e6b0SRob Clark /* Make all blocks contribute to the GPU BUSY perf counter: */ 1637198e6b0SRob Clark gpu_write(gpu, REG_A3XX_RBBM_GPU_BUSY_MASKED, 0xffffffff); 1647198e6b0SRob Clark 1657198e6b0SRob Clark /* Tune the hystersis counters for SP and CP idle detection: */ 1667198e6b0SRob Clark gpu_write(gpu, REG_A3XX_RBBM_SP_HYST_CNT, 0x10); 1677198e6b0SRob Clark gpu_write(gpu, REG_A3XX_RBBM_WAIT_IDLE_CLOCKS_CTL, 0x10); 1687198e6b0SRob Clark 1697198e6b0SRob Clark /* Enable the RBBM error reporting bits. This lets us get 1707198e6b0SRob Clark * useful information on failure: 1717198e6b0SRob Clark */ 1727198e6b0SRob Clark gpu_write(gpu, REG_A3XX_RBBM_AHB_CTL0, 0x00000001); 1737198e6b0SRob Clark 1747198e6b0SRob Clark /* Enable AHB error reporting: */ 1757198e6b0SRob Clark gpu_write(gpu, REG_A3XX_RBBM_AHB_CTL1, 0xa6ffffff); 1767198e6b0SRob Clark 1777198e6b0SRob Clark /* Turn on the power counters: */ 1787198e6b0SRob Clark gpu_write(gpu, REG_A3XX_RBBM_RBBM_CTL, 0x00030000); 1797198e6b0SRob Clark 1807198e6b0SRob Clark /* Turn on hang detection - this spews a lot of useful information 1817198e6b0SRob Clark * into the RBBM registers on a hang: 1827198e6b0SRob Clark */ 1837198e6b0SRob Clark gpu_write(gpu, REG_A3XX_RBBM_INTERFACE_HANG_INT_CTL, 0x00010fff); 1847198e6b0SRob Clark 1857198e6b0SRob Clark /* Enable 64-byte cacheline size. HW Default is 32-byte (0x000000E0): */ 1867198e6b0SRob Clark gpu_write(gpu, REG_A3XX_UCHE_CACHE_MODE_CONTROL_REG, 0x00000001); 1877198e6b0SRob Clark 1887198e6b0SRob Clark /* Enable Clock gating: */ 18955459968SRob Clark if (adreno_is_a320(adreno_gpu)) 1907198e6b0SRob Clark gpu_write(gpu, REG_A3XX_RBBM_CLOCK_CTL, 0xbfffffff); 19155459968SRob Clark else if (adreno_is_a330v2(adreno_gpu)) 19255459968SRob Clark gpu_write(gpu, REG_A3XX_RBBM_CLOCK_CTL, 0xaaaaaaaa); 19355459968SRob Clark else if (adreno_is_a330(adreno_gpu)) 19455459968SRob Clark gpu_write(gpu, REG_A3XX_RBBM_CLOCK_CTL, 0xbffcffff); 1957198e6b0SRob Clark 19655459968SRob Clark if (adreno_is_a330v2(adreno_gpu)) 19755459968SRob Clark gpu_write(gpu, REG_A3XX_RBBM_GPR0_CTL, 0x05515455); 19855459968SRob Clark else if (adreno_is_a330(adreno_gpu)) 19955459968SRob Clark gpu_write(gpu, REG_A3XX_RBBM_GPR0_CTL, 0x00000000); 20055459968SRob Clark 20155459968SRob Clark /* Set the OCMEM base address for A330, etc */ 20255459968SRob Clark if (a3xx_gpu->ocmem_hdl) { 20355459968SRob Clark gpu_write(gpu, REG_A3XX_RB_GMEM_BASE_ADDR, 20455459968SRob Clark (unsigned int)(a3xx_gpu->ocmem_base >> 14)); 20555459968SRob Clark } 2067198e6b0SRob Clark 2077198e6b0SRob Clark /* Turn on performance counters: */ 2087198e6b0SRob Clark gpu_write(gpu, REG_A3XX_RBBM_PERFCTR_CTL, 0x01); 2097198e6b0SRob Clark 210*70c70f09SRob Clark /* Enable the perfcntrs that we use.. */ 211*70c70f09SRob Clark for (i = 0; i < gpu->num_perfcntrs; i++) { 212*70c70f09SRob Clark const struct msm_gpu_perfcntr *perfcntr = &gpu->perfcntrs[i]; 213*70c70f09SRob Clark gpu_write(gpu, perfcntr->select_reg, perfcntr->select_val); 214*70c70f09SRob Clark } 2157198e6b0SRob Clark 2167198e6b0SRob Clark gpu_write(gpu, REG_A3XX_RBBM_INT_0_MASK, A3XX_INT0_MASK); 2177198e6b0SRob Clark 2187198e6b0SRob Clark ret = adreno_hw_init(gpu); 2197198e6b0SRob Clark if (ret) 2207198e6b0SRob Clark return ret; 2217198e6b0SRob Clark 2227198e6b0SRob Clark /* setup access protection: */ 2237198e6b0SRob Clark gpu_write(gpu, REG_A3XX_CP_PROTECT_CTRL, 0x00000007); 2247198e6b0SRob Clark 2257198e6b0SRob Clark /* RBBM registers */ 2267198e6b0SRob Clark gpu_write(gpu, REG_A3XX_CP_PROTECT(0), 0x63000040); 2277198e6b0SRob Clark gpu_write(gpu, REG_A3XX_CP_PROTECT(1), 0x62000080); 2287198e6b0SRob Clark gpu_write(gpu, REG_A3XX_CP_PROTECT(2), 0x600000cc); 2297198e6b0SRob Clark gpu_write(gpu, REG_A3XX_CP_PROTECT(3), 0x60000108); 2307198e6b0SRob Clark gpu_write(gpu, REG_A3XX_CP_PROTECT(4), 0x64000140); 2317198e6b0SRob Clark gpu_write(gpu, REG_A3XX_CP_PROTECT(5), 0x66000400); 2327198e6b0SRob Clark 2337198e6b0SRob Clark /* CP registers */ 2347198e6b0SRob Clark gpu_write(gpu, REG_A3XX_CP_PROTECT(6), 0x65000700); 2357198e6b0SRob Clark gpu_write(gpu, REG_A3XX_CP_PROTECT(7), 0x610007d8); 2367198e6b0SRob Clark gpu_write(gpu, REG_A3XX_CP_PROTECT(8), 0x620007e0); 2377198e6b0SRob Clark gpu_write(gpu, REG_A3XX_CP_PROTECT(9), 0x61001178); 2387198e6b0SRob Clark gpu_write(gpu, REG_A3XX_CP_PROTECT(10), 0x64001180); 2397198e6b0SRob Clark 2407198e6b0SRob Clark /* RB registers */ 2417198e6b0SRob Clark gpu_write(gpu, REG_A3XX_CP_PROTECT(11), 0x60003300); 2427198e6b0SRob Clark 2437198e6b0SRob Clark /* VBIF registers */ 2447198e6b0SRob Clark gpu_write(gpu, REG_A3XX_CP_PROTECT(12), 0x6b00c000); 2457198e6b0SRob Clark 2467198e6b0SRob Clark /* NOTE: PM4/micro-engine firmware registers look to be the same 2477198e6b0SRob Clark * for a2xx and a3xx.. we could possibly push that part down to 2487198e6b0SRob Clark * adreno_gpu base class. Or push both PM4 and PFP but 2497198e6b0SRob Clark * parameterize the pfp ucode addr/data registers.. 2507198e6b0SRob Clark */ 2517198e6b0SRob Clark 2527198e6b0SRob Clark /* Load PM4: */ 2537198e6b0SRob Clark ptr = (uint32_t *)(adreno_gpu->pm4->data); 2547198e6b0SRob Clark len = adreno_gpu->pm4->size / 4; 255e529c7e6SRob Clark DBG("loading PM4 ucode version: %x", ptr[1]); 2567198e6b0SRob Clark 2577198e6b0SRob Clark gpu_write(gpu, REG_AXXX_CP_DEBUG, 2587198e6b0SRob Clark AXXX_CP_DEBUG_DYNAMIC_CLK_DISABLE | 2597198e6b0SRob Clark AXXX_CP_DEBUG_MIU_128BIT_WRITE_ENABLE); 2607198e6b0SRob Clark gpu_write(gpu, REG_AXXX_CP_ME_RAM_WADDR, 0); 2617198e6b0SRob Clark for (i = 1; i < len; i++) 2627198e6b0SRob Clark gpu_write(gpu, REG_AXXX_CP_ME_RAM_DATA, ptr[i]); 2637198e6b0SRob Clark 2647198e6b0SRob Clark /* Load PFP: */ 2657198e6b0SRob Clark ptr = (uint32_t *)(adreno_gpu->pfp->data); 2667198e6b0SRob Clark len = adreno_gpu->pfp->size / 4; 267e529c7e6SRob Clark DBG("loading PFP ucode version: %x", ptr[5]); 2687198e6b0SRob Clark 2697198e6b0SRob Clark gpu_write(gpu, REG_A3XX_CP_PFP_UCODE_ADDR, 0); 2707198e6b0SRob Clark for (i = 1; i < len; i++) 2717198e6b0SRob Clark gpu_write(gpu, REG_A3XX_CP_PFP_UCODE_DATA, ptr[i]); 2727198e6b0SRob Clark 2737198e6b0SRob Clark /* CP ROQ queue sizes (bytes) - RB:16, ST:16, IB1:32, IB2:64 */ 27455459968SRob Clark if (adreno_is_a305(adreno_gpu) || adreno_is_a320(adreno_gpu)) { 2757198e6b0SRob Clark gpu_write(gpu, REG_AXXX_CP_QUEUE_THRESHOLDS, 2767198e6b0SRob Clark AXXX_CP_QUEUE_THRESHOLDS_CSQ_IB1_START(2) | 2777198e6b0SRob Clark AXXX_CP_QUEUE_THRESHOLDS_CSQ_IB2_START(6) | 2787198e6b0SRob Clark AXXX_CP_QUEUE_THRESHOLDS_CSQ_ST_START(14)); 27955459968SRob Clark } else if (adreno_is_a330(adreno_gpu)) { 28055459968SRob Clark /* NOTE: this (value take from downstream android driver) 28155459968SRob Clark * includes some bits outside of the known bitfields. But 28255459968SRob Clark * A330 has this "MERCIU queue" thing too, which might 28355459968SRob Clark * explain a new bitfield or reshuffling: 28455459968SRob Clark */ 28555459968SRob Clark gpu_write(gpu, REG_AXXX_CP_QUEUE_THRESHOLDS, 0x003e2008); 28655459968SRob Clark } 2877198e6b0SRob Clark 2887198e6b0SRob Clark /* clear ME_HALT to start micro engine */ 2897198e6b0SRob Clark gpu_write(gpu, REG_AXXX_CP_ME_CNTL, 0); 2907198e6b0SRob Clark 2917198e6b0SRob Clark a3xx_me_init(gpu); 2927198e6b0SRob Clark 2937198e6b0SRob Clark return 0; 2947198e6b0SRob Clark } 2957198e6b0SRob Clark 29655459968SRob Clark static void a3xx_recover(struct msm_gpu *gpu) 29755459968SRob Clark { 2985b6ef08eSRob Clark /* dump registers before resetting gpu, if enabled: */ 2995b6ef08eSRob Clark if (hang_debug) 3005b6ef08eSRob Clark a3xx_dump(gpu); 30155459968SRob Clark gpu_write(gpu, REG_A3XX_RBBM_SW_RESET_CMD, 1); 30255459968SRob Clark gpu_read(gpu, REG_A3XX_RBBM_SW_RESET_CMD); 30355459968SRob Clark gpu_write(gpu, REG_A3XX_RBBM_SW_RESET_CMD, 0); 30455459968SRob Clark adreno_recover(gpu); 30555459968SRob Clark } 30655459968SRob Clark 3077198e6b0SRob Clark static void a3xx_destroy(struct msm_gpu *gpu) 3087198e6b0SRob Clark { 3097198e6b0SRob Clark struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 3107198e6b0SRob Clark struct a3xx_gpu *a3xx_gpu = to_a3xx_gpu(adreno_gpu); 3117198e6b0SRob Clark 3127198e6b0SRob Clark DBG("%s", gpu->name); 3137198e6b0SRob Clark 3147198e6b0SRob Clark adreno_gpu_cleanup(adreno_gpu); 31555459968SRob Clark 31655459968SRob Clark #ifdef CONFIG_MSM_OCMEM 31755459968SRob Clark if (a3xx_gpu->ocmem_base) 31855459968SRob Clark ocmem_free(OCMEM_GRAPHICS, a3xx_gpu->ocmem_hdl); 31955459968SRob Clark #endif 32055459968SRob Clark 3217198e6b0SRob Clark kfree(a3xx_gpu); 3227198e6b0SRob Clark } 3237198e6b0SRob Clark 3247198e6b0SRob Clark static void a3xx_idle(struct msm_gpu *gpu) 3257198e6b0SRob Clark { 3267198e6b0SRob Clark /* wait for ringbuffer to drain: */ 3277198e6b0SRob Clark adreno_idle(gpu); 3287198e6b0SRob Clark 3297198e6b0SRob Clark /* then wait for GPU to finish: */ 3300963756fSRob Clark if (spin_until(!(gpu_read(gpu, REG_A3XX_RBBM_STATUS) & 3310963756fSRob Clark A3XX_RBBM_STATUS_GPU_BUSY))) 3320963756fSRob Clark DRM_ERROR("%s: timeout waiting for GPU to idle!\n", gpu->name); 3337198e6b0SRob Clark 3347198e6b0SRob Clark /* TODO maybe we need to reset GPU here to recover from hang? */ 3357198e6b0SRob Clark } 3367198e6b0SRob Clark 3377198e6b0SRob Clark static irqreturn_t a3xx_irq(struct msm_gpu *gpu) 3387198e6b0SRob Clark { 3397198e6b0SRob Clark uint32_t status; 3407198e6b0SRob Clark 3417198e6b0SRob Clark status = gpu_read(gpu, REG_A3XX_RBBM_INT_0_STATUS); 3427198e6b0SRob Clark DBG("%s: %08x", gpu->name, status); 3437198e6b0SRob Clark 3447198e6b0SRob Clark // TODO 3457198e6b0SRob Clark 3467198e6b0SRob Clark gpu_write(gpu, REG_A3XX_RBBM_INT_CLEAR_CMD, status); 3477198e6b0SRob Clark 3487198e6b0SRob Clark msm_gpu_retire(gpu); 3497198e6b0SRob Clark 3507198e6b0SRob Clark return IRQ_HANDLED; 3517198e6b0SRob Clark } 3527198e6b0SRob Clark 3537198e6b0SRob Clark static const unsigned int a3xx_registers[] = { 3547198e6b0SRob Clark 0x0000, 0x0002, 0x0010, 0x0012, 0x0018, 0x0018, 0x0020, 0x0027, 3557198e6b0SRob Clark 0x0029, 0x002b, 0x002e, 0x0033, 0x0040, 0x0042, 0x0050, 0x005c, 3567198e6b0SRob Clark 0x0060, 0x006c, 0x0080, 0x0082, 0x0084, 0x0088, 0x0090, 0x00e5, 3577198e6b0SRob Clark 0x00ea, 0x00ed, 0x0100, 0x0100, 0x0110, 0x0123, 0x01c0, 0x01c1, 3587198e6b0SRob Clark 0x01c3, 0x01c5, 0x01c7, 0x01c7, 0x01d5, 0x01d9, 0x01dc, 0x01dd, 3597198e6b0SRob Clark 0x01ea, 0x01ea, 0x01ee, 0x01f1, 0x01f5, 0x01f5, 0x01fc, 0x01ff, 3607198e6b0SRob Clark 0x0440, 0x0440, 0x0443, 0x0443, 0x0445, 0x0445, 0x044d, 0x044f, 3617198e6b0SRob Clark 0x0452, 0x0452, 0x0454, 0x046f, 0x047c, 0x047c, 0x047f, 0x047f, 3627198e6b0SRob Clark 0x0578, 0x057f, 0x0600, 0x0602, 0x0605, 0x0607, 0x060a, 0x060e, 3637198e6b0SRob Clark 0x0612, 0x0614, 0x0c01, 0x0c02, 0x0c06, 0x0c1d, 0x0c3d, 0x0c3f, 3647198e6b0SRob Clark 0x0c48, 0x0c4b, 0x0c80, 0x0c80, 0x0c88, 0x0c8b, 0x0ca0, 0x0cb7, 3657198e6b0SRob Clark 0x0cc0, 0x0cc1, 0x0cc6, 0x0cc7, 0x0ce4, 0x0ce5, 0x0e00, 0x0e05, 3667198e6b0SRob Clark 0x0e0c, 0x0e0c, 0x0e22, 0x0e23, 0x0e41, 0x0e45, 0x0e64, 0x0e65, 3677198e6b0SRob Clark 0x0e80, 0x0e82, 0x0e84, 0x0e89, 0x0ea0, 0x0ea1, 0x0ea4, 0x0ea7, 3687198e6b0SRob Clark 0x0ec4, 0x0ecb, 0x0ee0, 0x0ee0, 0x0f00, 0x0f01, 0x0f03, 0x0f09, 3697198e6b0SRob Clark 0x2040, 0x2040, 0x2044, 0x2044, 0x2048, 0x204d, 0x2068, 0x2069, 3707198e6b0SRob Clark 0x206c, 0x206d, 0x2070, 0x2070, 0x2072, 0x2072, 0x2074, 0x2075, 3717198e6b0SRob Clark 0x2079, 0x207a, 0x20c0, 0x20d3, 0x20e4, 0x20ef, 0x2100, 0x2109, 3727198e6b0SRob Clark 0x210c, 0x210c, 0x210e, 0x210e, 0x2110, 0x2111, 0x2114, 0x2115, 3737198e6b0SRob Clark 0x21e4, 0x21e4, 0x21ea, 0x21ea, 0x21ec, 0x21ed, 0x21f0, 0x21f0, 3747198e6b0SRob Clark 0x2200, 0x2212, 0x2214, 0x2217, 0x221a, 0x221a, 0x2240, 0x227e, 3757198e6b0SRob Clark 0x2280, 0x228b, 0x22c0, 0x22c0, 0x22c4, 0x22ce, 0x22d0, 0x22d8, 3767198e6b0SRob Clark 0x22df, 0x22e6, 0x22e8, 0x22e9, 0x22ec, 0x22ec, 0x22f0, 0x22f7, 3777198e6b0SRob Clark 0x22ff, 0x22ff, 0x2340, 0x2343, 0x2348, 0x2349, 0x2350, 0x2356, 3787198e6b0SRob Clark 0x2360, 0x2360, 0x2440, 0x2440, 0x2444, 0x2444, 0x2448, 0x244d, 3797198e6b0SRob Clark 0x2468, 0x2469, 0x246c, 0x246d, 0x2470, 0x2470, 0x2472, 0x2472, 3807198e6b0SRob Clark 0x2474, 0x2475, 0x2479, 0x247a, 0x24c0, 0x24d3, 0x24e4, 0x24ef, 3817198e6b0SRob Clark 0x2500, 0x2509, 0x250c, 0x250c, 0x250e, 0x250e, 0x2510, 0x2511, 3827198e6b0SRob Clark 0x2514, 0x2515, 0x25e4, 0x25e4, 0x25ea, 0x25ea, 0x25ec, 0x25ed, 3837198e6b0SRob Clark 0x25f0, 0x25f0, 0x2600, 0x2612, 0x2614, 0x2617, 0x261a, 0x261a, 3847198e6b0SRob Clark 0x2640, 0x267e, 0x2680, 0x268b, 0x26c0, 0x26c0, 0x26c4, 0x26ce, 3857198e6b0SRob Clark 0x26d0, 0x26d8, 0x26df, 0x26e6, 0x26e8, 0x26e9, 0x26ec, 0x26ec, 3867198e6b0SRob Clark 0x26f0, 0x26f7, 0x26ff, 0x26ff, 0x2740, 0x2743, 0x2748, 0x2749, 3877198e6b0SRob Clark 0x2750, 0x2756, 0x2760, 0x2760, 0x300c, 0x300e, 0x301c, 0x301d, 3887198e6b0SRob Clark 0x302a, 0x302a, 0x302c, 0x302d, 0x3030, 0x3031, 0x3034, 0x3036, 3897198e6b0SRob Clark 0x303c, 0x303c, 0x305e, 0x305f, 3907198e6b0SRob Clark }; 3917198e6b0SRob Clark 3925b6ef08eSRob Clark #ifdef CONFIG_DEBUG_FS 3937198e6b0SRob Clark static void a3xx_show(struct msm_gpu *gpu, struct seq_file *m) 3947198e6b0SRob Clark { 39537d77c3aSRob Clark struct drm_device *dev = gpu->dev; 3967198e6b0SRob Clark int i; 3977198e6b0SRob Clark 3987198e6b0SRob Clark adreno_show(gpu, m); 39937d77c3aSRob Clark 40037d77c3aSRob Clark mutex_lock(&dev->struct_mutex); 40137d77c3aSRob Clark 40237d77c3aSRob Clark gpu->funcs->pm_resume(gpu); 40337d77c3aSRob Clark 4047198e6b0SRob Clark seq_printf(m, "status: %08x\n", 4057198e6b0SRob Clark gpu_read(gpu, REG_A3XX_RBBM_STATUS)); 4067198e6b0SRob Clark 4077198e6b0SRob Clark /* dump these out in a form that can be parsed by demsm: */ 4087198e6b0SRob Clark seq_printf(m, "IO:region %s 00000000 00020000\n", gpu->name); 4097198e6b0SRob Clark for (i = 0; i < ARRAY_SIZE(a3xx_registers); i += 2) { 4107198e6b0SRob Clark uint32_t start = a3xx_registers[i]; 4117198e6b0SRob Clark uint32_t end = a3xx_registers[i+1]; 4127198e6b0SRob Clark uint32_t addr; 4137198e6b0SRob Clark 4147198e6b0SRob Clark for (addr = start; addr <= end; addr++) { 4157198e6b0SRob Clark uint32_t val = gpu_read(gpu, addr); 4167198e6b0SRob Clark seq_printf(m, "IO:R %08x %08x\n", addr<<2, val); 4177198e6b0SRob Clark } 4187198e6b0SRob Clark } 41937d77c3aSRob Clark 42037d77c3aSRob Clark gpu->funcs->pm_suspend(gpu); 42137d77c3aSRob Clark 42237d77c3aSRob Clark mutex_unlock(&dev->struct_mutex); 4237198e6b0SRob Clark } 4247198e6b0SRob Clark #endif 4257198e6b0SRob Clark 4265b6ef08eSRob Clark /* would be nice to not have to duplicate the _show() stuff with printk(): */ 4275b6ef08eSRob Clark static void a3xx_dump(struct msm_gpu *gpu) 4285b6ef08eSRob Clark { 4295b6ef08eSRob Clark int i; 4305b6ef08eSRob Clark 4315b6ef08eSRob Clark adreno_dump(gpu); 4325b6ef08eSRob Clark printk("status: %08x\n", 4335b6ef08eSRob Clark gpu_read(gpu, REG_A3XX_RBBM_STATUS)); 4345b6ef08eSRob Clark 4355b6ef08eSRob Clark /* dump these out in a form that can be parsed by demsm: */ 4365b6ef08eSRob Clark printk("IO:region %s 00000000 00020000\n", gpu->name); 4375b6ef08eSRob Clark for (i = 0; i < ARRAY_SIZE(a3xx_registers); i += 2) { 4385b6ef08eSRob Clark uint32_t start = a3xx_registers[i]; 4395b6ef08eSRob Clark uint32_t end = a3xx_registers[i+1]; 4405b6ef08eSRob Clark uint32_t addr; 4415b6ef08eSRob Clark 4425b6ef08eSRob Clark for (addr = start; addr <= end; addr++) { 4435b6ef08eSRob Clark uint32_t val = gpu_read(gpu, addr); 4445b6ef08eSRob Clark printk("IO:R %08x %08x\n", addr<<2, val); 4455b6ef08eSRob Clark } 4465b6ef08eSRob Clark } 4475b6ef08eSRob Clark } 4485b6ef08eSRob Clark 4497198e6b0SRob Clark static const struct adreno_gpu_funcs funcs = { 4507198e6b0SRob Clark .base = { 4517198e6b0SRob Clark .get_param = adreno_get_param, 4527198e6b0SRob Clark .hw_init = a3xx_hw_init, 4537198e6b0SRob Clark .pm_suspend = msm_gpu_pm_suspend, 4547198e6b0SRob Clark .pm_resume = msm_gpu_pm_resume, 45555459968SRob Clark .recover = a3xx_recover, 4567198e6b0SRob Clark .last_fence = adreno_last_fence, 4577198e6b0SRob Clark .submit = adreno_submit, 4587198e6b0SRob Clark .flush = adreno_flush, 4597198e6b0SRob Clark .idle = a3xx_idle, 4607198e6b0SRob Clark .irq = a3xx_irq, 4617198e6b0SRob Clark .destroy = a3xx_destroy, 4627198e6b0SRob Clark #ifdef CONFIG_DEBUG_FS 4637198e6b0SRob Clark .show = a3xx_show, 4647198e6b0SRob Clark #endif 4657198e6b0SRob Clark }, 4667198e6b0SRob Clark }; 4677198e6b0SRob Clark 468*70c70f09SRob Clark static const struct msm_gpu_perfcntr perfcntrs[] = { 469*70c70f09SRob Clark { REG_A3XX_SP_PERFCOUNTER6_SELECT, REG_A3XX_RBBM_PERFCTR_SP_6_LO, 470*70c70f09SRob Clark SP_ALU_ACTIVE_CYCLES, "ALUACTIVE" }, 471*70c70f09SRob Clark { REG_A3XX_SP_PERFCOUNTER7_SELECT, REG_A3XX_RBBM_PERFCTR_SP_7_LO, 472*70c70f09SRob Clark SP_FS_FULL_ALU_INSTRUCTIONS, "ALUFULL" }, 473*70c70f09SRob Clark }; 474*70c70f09SRob Clark 4757198e6b0SRob Clark struct msm_gpu *a3xx_gpu_init(struct drm_device *dev) 4767198e6b0SRob Clark { 4777198e6b0SRob Clark struct a3xx_gpu *a3xx_gpu = NULL; 47855459968SRob Clark struct adreno_gpu *adreno_gpu; 4797198e6b0SRob Clark struct msm_gpu *gpu; 480060530f1SRob Clark struct msm_drm_private *priv = dev->dev_private; 481060530f1SRob Clark struct platform_device *pdev = priv->gpu_pdev; 4827198e6b0SRob Clark struct adreno_platform_config *config; 4837198e6b0SRob Clark int ret; 4847198e6b0SRob Clark 4857198e6b0SRob Clark if (!pdev) { 4867198e6b0SRob Clark dev_err(dev->dev, "no a3xx device\n"); 4877198e6b0SRob Clark ret = -ENXIO; 4887198e6b0SRob Clark goto fail; 4897198e6b0SRob Clark } 4907198e6b0SRob Clark 4917198e6b0SRob Clark config = pdev->dev.platform_data; 4927198e6b0SRob Clark 4937198e6b0SRob Clark a3xx_gpu = kzalloc(sizeof(*a3xx_gpu), GFP_KERNEL); 4947198e6b0SRob Clark if (!a3xx_gpu) { 4957198e6b0SRob Clark ret = -ENOMEM; 4967198e6b0SRob Clark goto fail; 4977198e6b0SRob Clark } 4987198e6b0SRob Clark 49955459968SRob Clark adreno_gpu = &a3xx_gpu->base; 50055459968SRob Clark gpu = &adreno_gpu->base; 5017198e6b0SRob Clark 5027198e6b0SRob Clark a3xx_gpu->pdev = pdev; 5037198e6b0SRob Clark 5047198e6b0SRob Clark gpu->fast_rate = config->fast_rate; 5057198e6b0SRob Clark gpu->slow_rate = config->slow_rate; 5067198e6b0SRob Clark gpu->bus_freq = config->bus_freq; 507bf2b33afSRob Clark #ifdef CONFIG_MSM_BUS_SCALING 508bf2b33afSRob Clark gpu->bus_scale_table = config->bus_scale_table; 509bf2b33afSRob Clark #endif 5107198e6b0SRob Clark 5117198e6b0SRob Clark DBG("fast_rate=%u, slow_rate=%u, bus_freq=%u", 5127198e6b0SRob Clark gpu->fast_rate, gpu->slow_rate, gpu->bus_freq); 5137198e6b0SRob Clark 514*70c70f09SRob Clark gpu->perfcntrs = perfcntrs; 515*70c70f09SRob Clark gpu->num_perfcntrs = ARRAY_SIZE(perfcntrs); 516*70c70f09SRob Clark 51755459968SRob Clark ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, config->rev); 5187198e6b0SRob Clark if (ret) 5197198e6b0SRob Clark goto fail; 5207198e6b0SRob Clark 52155459968SRob Clark /* if needed, allocate gmem: */ 52255459968SRob Clark if (adreno_is_a330(adreno_gpu)) { 52355459968SRob Clark #ifdef CONFIG_MSM_OCMEM 52455459968SRob Clark /* TODO this is different/missing upstream: */ 52555459968SRob Clark struct ocmem_buf *ocmem_hdl = 52655459968SRob Clark ocmem_allocate(OCMEM_GRAPHICS, adreno_gpu->gmem); 52755459968SRob Clark 52855459968SRob Clark a3xx_gpu->ocmem_hdl = ocmem_hdl; 52955459968SRob Clark a3xx_gpu->ocmem_base = ocmem_hdl->addr; 53055459968SRob Clark adreno_gpu->gmem = ocmem_hdl->len; 53155459968SRob Clark DBG("using %dK of OCMEM at 0x%08x", adreno_gpu->gmem / 1024, 53255459968SRob Clark a3xx_gpu->ocmem_base); 53355459968SRob Clark #endif 53455459968SRob Clark } 53555459968SRob Clark 536871d812aSRob Clark if (!gpu->mmu) { 537871d812aSRob Clark /* TODO we think it is possible to configure the GPU to 538871d812aSRob Clark * restrict access to VRAM carveout. But the required 539871d812aSRob Clark * registers are unknown. For now just bail out and 540871d812aSRob Clark * limp along with just modesetting. If it turns out 541871d812aSRob Clark * to not be possible to restrict access, then we must 542871d812aSRob Clark * implement a cmdstream validator. 543871d812aSRob Clark */ 544871d812aSRob Clark dev_err(dev->dev, "No memory protection without IOMMU\n"); 545871d812aSRob Clark ret = -ENXIO; 546871d812aSRob Clark goto fail; 547871d812aSRob Clark } 548871d812aSRob Clark 549871d812aSRob Clark return gpu; 5507198e6b0SRob Clark 5517198e6b0SRob Clark fail: 5527198e6b0SRob Clark if (a3xx_gpu) 5537198e6b0SRob Clark a3xx_destroy(&a3xx_gpu->base.base); 5547198e6b0SRob Clark 5557198e6b0SRob Clark return ERR_PTR(ret); 5567198e6b0SRob Clark } 5577198e6b0SRob Clark 5587198e6b0SRob Clark /* 5597198e6b0SRob Clark * The a3xx device: 5607198e6b0SRob Clark */ 5617198e6b0SRob Clark 562bf2b33afSRob Clark #if defined(CONFIG_MSM_BUS_SCALING) && !defined(CONFIG_OF) 563bf2b33afSRob Clark # include <mach/kgsl.h> 564bf2b33afSRob Clark #endif 565bf2b33afSRob Clark 566060530f1SRob Clark static void set_gpu_pdev(struct drm_device *dev, 567060530f1SRob Clark struct platform_device *pdev) 568060530f1SRob Clark { 569060530f1SRob Clark struct msm_drm_private *priv = dev->dev_private; 570060530f1SRob Clark priv->gpu_pdev = pdev; 571060530f1SRob Clark } 572060530f1SRob Clark 573060530f1SRob Clark static int a3xx_bind(struct device *dev, struct device *master, void *data) 5747198e6b0SRob Clark { 5757198e6b0SRob Clark static struct adreno_platform_config config = {}; 5767198e6b0SRob Clark #ifdef CONFIG_OF 577060530f1SRob Clark struct device_node *child, *node = dev->of_node; 57855459968SRob Clark u32 val; 57955459968SRob Clark int ret; 58055459968SRob Clark 58155459968SRob Clark ret = of_property_read_u32(node, "qcom,chipid", &val); 58255459968SRob Clark if (ret) { 583060530f1SRob Clark dev_err(dev, "could not find chipid: %d\n", ret); 58455459968SRob Clark return ret; 58555459968SRob Clark } 58655459968SRob Clark 58755459968SRob Clark config.rev = ADRENO_REV((val >> 24) & 0xff, 58855459968SRob Clark (val >> 16) & 0xff, (val >> 8) & 0xff, val & 0xff); 58955459968SRob Clark 59055459968SRob Clark /* find clock rates: */ 59155459968SRob Clark config.fast_rate = 0; 59255459968SRob Clark config.slow_rate = ~0; 59355459968SRob Clark for_each_child_of_node(node, child) { 59455459968SRob Clark if (of_device_is_compatible(child, "qcom,gpu-pwrlevels")) { 59555459968SRob Clark struct device_node *pwrlvl; 59655459968SRob Clark for_each_child_of_node(child, pwrlvl) { 59755459968SRob Clark ret = of_property_read_u32(pwrlvl, "qcom,gpu-freq", &val); 59855459968SRob Clark if (ret) { 599060530f1SRob Clark dev_err(dev, "could not find gpu-freq: %d\n", ret); 60055459968SRob Clark return ret; 60155459968SRob Clark } 60255459968SRob Clark config.fast_rate = max(config.fast_rate, val); 60355459968SRob Clark config.slow_rate = min(config.slow_rate, val); 60455459968SRob Clark } 60555459968SRob Clark } 60655459968SRob Clark } 60755459968SRob Clark 60855459968SRob Clark if (!config.fast_rate) { 609060530f1SRob Clark dev_err(dev, "could not find clk rates\n"); 61055459968SRob Clark return -ENXIO; 61155459968SRob Clark } 61255459968SRob Clark 6137198e6b0SRob Clark #else 614060530f1SRob Clark struct kgsl_device_platform_data *pdata = dev->platform_data; 6157198e6b0SRob Clark uint32_t version = socinfo_get_version(); 6167198e6b0SRob Clark if (cpu_is_apq8064ab()) { 6177198e6b0SRob Clark config.fast_rate = 450000000; 6187198e6b0SRob Clark config.slow_rate = 27000000; 6197198e6b0SRob Clark config.bus_freq = 4; 6207198e6b0SRob Clark config.rev = ADRENO_REV(3, 2, 1, 0); 621e529c7e6SRob Clark } else if (cpu_is_apq8064()) { 6227198e6b0SRob Clark config.fast_rate = 400000000; 6237198e6b0SRob Clark config.slow_rate = 27000000; 6247198e6b0SRob Clark config.bus_freq = 4; 6257198e6b0SRob Clark 6267198e6b0SRob Clark if (SOCINFO_VERSION_MAJOR(version) == 2) 6277198e6b0SRob Clark config.rev = ADRENO_REV(3, 2, 0, 2); 6287198e6b0SRob Clark else if ((SOCINFO_VERSION_MAJOR(version) == 1) && 6297198e6b0SRob Clark (SOCINFO_VERSION_MINOR(version) == 1)) 6307198e6b0SRob Clark config.rev = ADRENO_REV(3, 2, 0, 1); 6317198e6b0SRob Clark else 6327198e6b0SRob Clark config.rev = ADRENO_REV(3, 2, 0, 0); 6337198e6b0SRob Clark 634e529c7e6SRob Clark } else if (cpu_is_msm8960ab()) { 635e529c7e6SRob Clark config.fast_rate = 400000000; 636e529c7e6SRob Clark config.slow_rate = 320000000; 637e529c7e6SRob Clark config.bus_freq = 4; 638e529c7e6SRob Clark 639e529c7e6SRob Clark if (SOCINFO_VERSION_MINOR(version) == 0) 640e529c7e6SRob Clark config.rev = ADRENO_REV(3, 2, 1, 0); 641e529c7e6SRob Clark else 642e529c7e6SRob Clark config.rev = ADRENO_REV(3, 2, 1, 1); 643e529c7e6SRob Clark 6447198e6b0SRob Clark } else if (cpu_is_msm8930()) { 6457198e6b0SRob Clark config.fast_rate = 400000000; 6467198e6b0SRob Clark config.slow_rate = 27000000; 6477198e6b0SRob Clark config.bus_freq = 3; 6487198e6b0SRob Clark 6497198e6b0SRob Clark if ((SOCINFO_VERSION_MAJOR(version) == 1) && 6507198e6b0SRob Clark (SOCINFO_VERSION_MINOR(version) == 2)) 6517198e6b0SRob Clark config.rev = ADRENO_REV(3, 0, 5, 2); 6527198e6b0SRob Clark else 6537198e6b0SRob Clark config.rev = ADRENO_REV(3, 0, 5, 0); 6547198e6b0SRob Clark 6557198e6b0SRob Clark } 656bf2b33afSRob Clark # ifdef CONFIG_MSM_BUS_SCALING 657bf2b33afSRob Clark config.bus_scale_table = pdata->bus_scale_table; 658bf2b33afSRob Clark # endif 6597198e6b0SRob Clark #endif 660060530f1SRob Clark dev->platform_data = &config; 661060530f1SRob Clark set_gpu_pdev(dev_get_drvdata(master), to_platform_device(dev)); 6627198e6b0SRob Clark return 0; 6637198e6b0SRob Clark } 6647198e6b0SRob Clark 665060530f1SRob Clark static void a3xx_unbind(struct device *dev, struct device *master, 666060530f1SRob Clark void *data) 667060530f1SRob Clark { 668060530f1SRob Clark set_gpu_pdev(dev_get_drvdata(master), NULL); 669060530f1SRob Clark } 670060530f1SRob Clark 671060530f1SRob Clark static const struct component_ops a3xx_ops = { 672060530f1SRob Clark .bind = a3xx_bind, 673060530f1SRob Clark .unbind = a3xx_unbind, 674060530f1SRob Clark }; 675060530f1SRob Clark 676060530f1SRob Clark static int a3xx_probe(struct platform_device *pdev) 677060530f1SRob Clark { 678060530f1SRob Clark return component_add(&pdev->dev, &a3xx_ops); 679060530f1SRob Clark } 680060530f1SRob Clark 6817198e6b0SRob Clark static int a3xx_remove(struct platform_device *pdev) 6827198e6b0SRob Clark { 683060530f1SRob Clark component_del(&pdev->dev, &a3xx_ops); 6847198e6b0SRob Clark return 0; 6857198e6b0SRob Clark } 6867198e6b0SRob Clark 68755459968SRob Clark static const struct of_device_id dt_match[] = { 68855459968SRob Clark { .compatible = "qcom,kgsl-3d0" }, 68955459968SRob Clark {} 69055459968SRob Clark }; 69155459968SRob Clark 6927198e6b0SRob Clark static struct platform_driver a3xx_driver = { 6937198e6b0SRob Clark .probe = a3xx_probe, 6947198e6b0SRob Clark .remove = a3xx_remove, 69555459968SRob Clark .driver = { 69655459968SRob Clark .name = "kgsl-3d0", 69755459968SRob Clark .of_match_table = dt_match, 69855459968SRob Clark }, 6997198e6b0SRob Clark }; 7007198e6b0SRob Clark 7017198e6b0SRob Clark void __init a3xx_register(void) 7027198e6b0SRob Clark { 7037198e6b0SRob Clark platform_driver_register(&a3xx_driver); 7047198e6b0SRob Clark } 7057198e6b0SRob Clark 7067198e6b0SRob Clark void __exit a3xx_unregister(void) 7077198e6b0SRob Clark { 7087198e6b0SRob Clark platform_driver_unregister(&a3xx_driver); 7097198e6b0SRob Clark } 710