1*7198e6b0SRob Clark /* 2*7198e6b0SRob Clark * Copyright (C) 2013 Red Hat 3*7198e6b0SRob Clark * Author: Rob Clark <robdclark@gmail.com> 4*7198e6b0SRob Clark * 5*7198e6b0SRob Clark * This program is free software; you can redistribute it and/or modify it 6*7198e6b0SRob Clark * under the terms of the GNU General Public License version 2 as published by 7*7198e6b0SRob Clark * the Free Software Foundation. 8*7198e6b0SRob Clark * 9*7198e6b0SRob Clark * This program is distributed in the hope that it will be useful, but WITHOUT 10*7198e6b0SRob Clark * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11*7198e6b0SRob Clark * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12*7198e6b0SRob Clark * more details. 13*7198e6b0SRob Clark * 14*7198e6b0SRob Clark * You should have received a copy of the GNU General Public License along with 15*7198e6b0SRob Clark * this program. If not, see <http://www.gnu.org/licenses/>. 16*7198e6b0SRob Clark */ 17*7198e6b0SRob Clark 18*7198e6b0SRob Clark #include "a3xx_gpu.h" 19*7198e6b0SRob Clark 20*7198e6b0SRob Clark #define A3XX_INT0_MASK \ 21*7198e6b0SRob Clark (A3XX_INT0_RBBM_AHB_ERROR | \ 22*7198e6b0SRob Clark A3XX_INT0_RBBM_ATB_BUS_OVERFLOW | \ 23*7198e6b0SRob Clark A3XX_INT0_CP_T0_PACKET_IN_IB | \ 24*7198e6b0SRob Clark A3XX_INT0_CP_OPCODE_ERROR | \ 25*7198e6b0SRob Clark A3XX_INT0_CP_RESERVED_BIT_ERROR | \ 26*7198e6b0SRob Clark A3XX_INT0_CP_HW_FAULT | \ 27*7198e6b0SRob Clark A3XX_INT0_CP_IB1_INT | \ 28*7198e6b0SRob Clark A3XX_INT0_CP_IB2_INT | \ 29*7198e6b0SRob Clark A3XX_INT0_CP_RB_INT | \ 30*7198e6b0SRob Clark A3XX_INT0_CP_REG_PROTECT_FAULT | \ 31*7198e6b0SRob Clark A3XX_INT0_CP_AHB_ERROR_HALT | \ 32*7198e6b0SRob Clark A3XX_INT0_UCHE_OOB_ACCESS) 33*7198e6b0SRob Clark 34*7198e6b0SRob Clark static struct platform_device *a3xx_pdev; 35*7198e6b0SRob Clark 36*7198e6b0SRob Clark static void a3xx_me_init(struct msm_gpu *gpu) 37*7198e6b0SRob Clark { 38*7198e6b0SRob Clark struct msm_ringbuffer *ring = gpu->rb; 39*7198e6b0SRob Clark 40*7198e6b0SRob Clark OUT_PKT3(ring, CP_ME_INIT, 17); 41*7198e6b0SRob Clark OUT_RING(ring, 0x000003f7); 42*7198e6b0SRob Clark OUT_RING(ring, 0x00000000); 43*7198e6b0SRob Clark OUT_RING(ring, 0x00000000); 44*7198e6b0SRob Clark OUT_RING(ring, 0x00000000); 45*7198e6b0SRob Clark OUT_RING(ring, 0x00000080); 46*7198e6b0SRob Clark OUT_RING(ring, 0x00000100); 47*7198e6b0SRob Clark OUT_RING(ring, 0x00000180); 48*7198e6b0SRob Clark OUT_RING(ring, 0x00006600); 49*7198e6b0SRob Clark OUT_RING(ring, 0x00000150); 50*7198e6b0SRob Clark OUT_RING(ring, 0x0000014e); 51*7198e6b0SRob Clark OUT_RING(ring, 0x00000154); 52*7198e6b0SRob Clark OUT_RING(ring, 0x00000001); 53*7198e6b0SRob Clark OUT_RING(ring, 0x00000000); 54*7198e6b0SRob Clark OUT_RING(ring, 0x00000000); 55*7198e6b0SRob Clark OUT_RING(ring, 0x00000000); 56*7198e6b0SRob Clark OUT_RING(ring, 0x00000000); 57*7198e6b0SRob Clark OUT_RING(ring, 0x00000000); 58*7198e6b0SRob Clark 59*7198e6b0SRob Clark gpu->funcs->flush(gpu); 60*7198e6b0SRob Clark gpu->funcs->idle(gpu); 61*7198e6b0SRob Clark } 62*7198e6b0SRob Clark 63*7198e6b0SRob Clark static int a3xx_hw_init(struct msm_gpu *gpu) 64*7198e6b0SRob Clark { 65*7198e6b0SRob Clark struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 66*7198e6b0SRob Clark uint32_t *ptr, len; 67*7198e6b0SRob Clark int i, ret; 68*7198e6b0SRob Clark 69*7198e6b0SRob Clark DBG("%s", gpu->name); 70*7198e6b0SRob Clark 71*7198e6b0SRob Clark if (adreno_is_a305(adreno_gpu)) { 72*7198e6b0SRob Clark /* Set up 16 deep read/write request queues: */ 73*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF0, 0x10101010); 74*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF1, 0x10101010); 75*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_OUT_RD_LIM_CONF0, 0x10101010); 76*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_OUT_WR_LIM_CONF0, 0x10101010); 77*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_DDR_OUT_MAX_BURST, 0x0000303); 78*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_IN_WR_LIM_CONF0, 0x10101010); 79*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_IN_WR_LIM_CONF1, 0x10101010); 80*7198e6b0SRob Clark /* Enable WR-REQ: */ 81*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_GATE_OFF_WRREQ_EN, 0x0000ff); 82*7198e6b0SRob Clark /* Set up round robin arbitration between both AXI ports: */ 83*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_ARB_CTL, 0x00000030); 84*7198e6b0SRob Clark /* Set up AOOO: */ 85*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO_EN, 0x0000003c); 86*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO, 0x003c003c); 87*7198e6b0SRob Clark 88*7198e6b0SRob Clark } else if (adreno_is_a320(adreno_gpu)) { 89*7198e6b0SRob Clark /* Set up 16 deep read/write request queues: */ 90*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF0, 0x10101010); 91*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF1, 0x10101010); 92*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_OUT_RD_LIM_CONF0, 0x10101010); 93*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_OUT_WR_LIM_CONF0, 0x10101010); 94*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_DDR_OUT_MAX_BURST, 0x0000303); 95*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_IN_WR_LIM_CONF0, 0x10101010); 96*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_IN_WR_LIM_CONF1, 0x10101010); 97*7198e6b0SRob Clark /* Enable WR-REQ: */ 98*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_GATE_OFF_WRREQ_EN, 0x0000ff); 99*7198e6b0SRob Clark /* Set up round robin arbitration between both AXI ports: */ 100*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_ARB_CTL, 0x00000030); 101*7198e6b0SRob Clark /* Set up AOOO: */ 102*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO_EN, 0x0000003c); 103*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO, 0x003c003c); 104*7198e6b0SRob Clark /* Enable 1K sort: */ 105*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT, 0x000000ff); 106*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT_CONF, 0x000000a4); 107*7198e6b0SRob Clark 108*7198e6b0SRob Clark } else if (adreno_is_a330(adreno_gpu)) { 109*7198e6b0SRob Clark /* Set up 16 deep read/write request queues: */ 110*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF0, 0x18181818); 111*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF1, 0x18181818); 112*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_OUT_RD_LIM_CONF0, 0x18181818); 113*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_OUT_WR_LIM_CONF0, 0x18181818); 114*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_DDR_OUT_MAX_BURST, 0x0000303); 115*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_IN_WR_LIM_CONF0, 0x18181818); 116*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_IN_WR_LIM_CONF1, 0x18181818); 117*7198e6b0SRob Clark /* Enable WR-REQ: */ 118*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_GATE_OFF_WRREQ_EN, 0x00003f); 119*7198e6b0SRob Clark /* Set up round robin arbitration between both AXI ports: */ 120*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_ARB_CTL, 0x00000030); 121*7198e6b0SRob Clark /* Set up VBIF_ROUND_ROBIN_QOS_ARB: */ 122*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x0001); 123*7198e6b0SRob Clark /* Set up AOOO: */ 124*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO_EN, 0x0000ffff); 125*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO, 0xffffffff); 126*7198e6b0SRob Clark /* Enable 1K sort: */ 127*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT, 0x0001ffff); 128*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_ABIT_SORT_CONF, 0x000000a4); 129*7198e6b0SRob Clark /* Disable VBIF clock gating. This is to enable AXI running 130*7198e6b0SRob Clark * higher frequency than GPU: 131*7198e6b0SRob Clark */ 132*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_VBIF_CLKON, 0x00000001); 133*7198e6b0SRob Clark 134*7198e6b0SRob Clark } else { 135*7198e6b0SRob Clark BUG(); 136*7198e6b0SRob Clark } 137*7198e6b0SRob Clark 138*7198e6b0SRob Clark /* Make all blocks contribute to the GPU BUSY perf counter: */ 139*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_RBBM_GPU_BUSY_MASKED, 0xffffffff); 140*7198e6b0SRob Clark 141*7198e6b0SRob Clark /* Tune the hystersis counters for SP and CP idle detection: */ 142*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_RBBM_SP_HYST_CNT, 0x10); 143*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_RBBM_WAIT_IDLE_CLOCKS_CTL, 0x10); 144*7198e6b0SRob Clark 145*7198e6b0SRob Clark /* Enable the RBBM error reporting bits. This lets us get 146*7198e6b0SRob Clark * useful information on failure: 147*7198e6b0SRob Clark */ 148*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_RBBM_AHB_CTL0, 0x00000001); 149*7198e6b0SRob Clark 150*7198e6b0SRob Clark /* Enable AHB error reporting: */ 151*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_RBBM_AHB_CTL1, 0xa6ffffff); 152*7198e6b0SRob Clark 153*7198e6b0SRob Clark /* Turn on the power counters: */ 154*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_RBBM_RBBM_CTL, 0x00030000); 155*7198e6b0SRob Clark 156*7198e6b0SRob Clark /* Turn on hang detection - this spews a lot of useful information 157*7198e6b0SRob Clark * into the RBBM registers on a hang: 158*7198e6b0SRob Clark */ 159*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_RBBM_INTERFACE_HANG_INT_CTL, 0x00010fff); 160*7198e6b0SRob Clark 161*7198e6b0SRob Clark /* Enable 64-byte cacheline size. HW Default is 32-byte (0x000000E0): */ 162*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_UCHE_CACHE_MODE_CONTROL_REG, 0x00000001); 163*7198e6b0SRob Clark 164*7198e6b0SRob Clark /* Enable Clock gating: */ 165*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_RBBM_CLOCK_CTL, 0xbfffffff); 166*7198e6b0SRob Clark 167*7198e6b0SRob Clark /* Set the OCMEM base address for A330 */ 168*7198e6b0SRob Clark //TODO: 169*7198e6b0SRob Clark // if (adreno_is_a330(adreno_gpu)) { 170*7198e6b0SRob Clark // gpu_write(gpu, REG_A3XX_RB_GMEM_BASE_ADDR, 171*7198e6b0SRob Clark // (unsigned int)(a3xx_gpu->ocmem_base >> 14)); 172*7198e6b0SRob Clark // } 173*7198e6b0SRob Clark 174*7198e6b0SRob Clark /* Turn on performance counters: */ 175*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_RBBM_PERFCTR_CTL, 0x01); 176*7198e6b0SRob Clark 177*7198e6b0SRob Clark /* Set SP perfcounter 7 to count SP_FS_FULL_ALU_INSTRUCTIONS 178*7198e6b0SRob Clark * we will use this to augment our hang detection: 179*7198e6b0SRob Clark */ 180*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_SP_PERFCOUNTER7_SELECT, 181*7198e6b0SRob Clark SP_FS_FULL_ALU_INSTRUCTIONS); 182*7198e6b0SRob Clark 183*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_RBBM_INT_0_MASK, A3XX_INT0_MASK); 184*7198e6b0SRob Clark 185*7198e6b0SRob Clark ret = adreno_hw_init(gpu); 186*7198e6b0SRob Clark if (ret) 187*7198e6b0SRob Clark return ret; 188*7198e6b0SRob Clark 189*7198e6b0SRob Clark /* setup access protection: */ 190*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_CP_PROTECT_CTRL, 0x00000007); 191*7198e6b0SRob Clark 192*7198e6b0SRob Clark /* RBBM registers */ 193*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_CP_PROTECT(0), 0x63000040); 194*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_CP_PROTECT(1), 0x62000080); 195*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_CP_PROTECT(2), 0x600000cc); 196*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_CP_PROTECT(3), 0x60000108); 197*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_CP_PROTECT(4), 0x64000140); 198*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_CP_PROTECT(5), 0x66000400); 199*7198e6b0SRob Clark 200*7198e6b0SRob Clark /* CP registers */ 201*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_CP_PROTECT(6), 0x65000700); 202*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_CP_PROTECT(7), 0x610007d8); 203*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_CP_PROTECT(8), 0x620007e0); 204*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_CP_PROTECT(9), 0x61001178); 205*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_CP_PROTECT(10), 0x64001180); 206*7198e6b0SRob Clark 207*7198e6b0SRob Clark /* RB registers */ 208*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_CP_PROTECT(11), 0x60003300); 209*7198e6b0SRob Clark 210*7198e6b0SRob Clark /* VBIF registers */ 211*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_CP_PROTECT(12), 0x6b00c000); 212*7198e6b0SRob Clark 213*7198e6b0SRob Clark /* NOTE: PM4/micro-engine firmware registers look to be the same 214*7198e6b0SRob Clark * for a2xx and a3xx.. we could possibly push that part down to 215*7198e6b0SRob Clark * adreno_gpu base class. Or push both PM4 and PFP but 216*7198e6b0SRob Clark * parameterize the pfp ucode addr/data registers.. 217*7198e6b0SRob Clark */ 218*7198e6b0SRob Clark 219*7198e6b0SRob Clark /* Load PM4: */ 220*7198e6b0SRob Clark ptr = (uint32_t *)(adreno_gpu->pm4->data); 221*7198e6b0SRob Clark len = adreno_gpu->pm4->size / 4; 222*7198e6b0SRob Clark DBG("loading PM4 ucode version: %u", ptr[0]); 223*7198e6b0SRob Clark 224*7198e6b0SRob Clark gpu_write(gpu, REG_AXXX_CP_DEBUG, 225*7198e6b0SRob Clark AXXX_CP_DEBUG_DYNAMIC_CLK_DISABLE | 226*7198e6b0SRob Clark AXXX_CP_DEBUG_MIU_128BIT_WRITE_ENABLE); 227*7198e6b0SRob Clark gpu_write(gpu, REG_AXXX_CP_ME_RAM_WADDR, 0); 228*7198e6b0SRob Clark for (i = 1; i < len; i++) 229*7198e6b0SRob Clark gpu_write(gpu, REG_AXXX_CP_ME_RAM_DATA, ptr[i]); 230*7198e6b0SRob Clark 231*7198e6b0SRob Clark /* Load PFP: */ 232*7198e6b0SRob Clark ptr = (uint32_t *)(adreno_gpu->pfp->data); 233*7198e6b0SRob Clark len = adreno_gpu->pfp->size / 4; 234*7198e6b0SRob Clark DBG("loading PFP ucode version: %u", ptr[0]); 235*7198e6b0SRob Clark 236*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_CP_PFP_UCODE_ADDR, 0); 237*7198e6b0SRob Clark for (i = 1; i < len; i++) 238*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_CP_PFP_UCODE_DATA, ptr[i]); 239*7198e6b0SRob Clark 240*7198e6b0SRob Clark /* CP ROQ queue sizes (bytes) - RB:16, ST:16, IB1:32, IB2:64 */ 241*7198e6b0SRob Clark if (adreno_is_a305(adreno_gpu) || adreno_is_a320(adreno_gpu)) 242*7198e6b0SRob Clark gpu_write(gpu, REG_AXXX_CP_QUEUE_THRESHOLDS, 243*7198e6b0SRob Clark AXXX_CP_QUEUE_THRESHOLDS_CSQ_IB1_START(2) | 244*7198e6b0SRob Clark AXXX_CP_QUEUE_THRESHOLDS_CSQ_IB2_START(6) | 245*7198e6b0SRob Clark AXXX_CP_QUEUE_THRESHOLDS_CSQ_ST_START(14)); 246*7198e6b0SRob Clark 247*7198e6b0SRob Clark 248*7198e6b0SRob Clark /* clear ME_HALT to start micro engine */ 249*7198e6b0SRob Clark gpu_write(gpu, REG_AXXX_CP_ME_CNTL, 0); 250*7198e6b0SRob Clark 251*7198e6b0SRob Clark a3xx_me_init(gpu); 252*7198e6b0SRob Clark 253*7198e6b0SRob Clark return 0; 254*7198e6b0SRob Clark } 255*7198e6b0SRob Clark 256*7198e6b0SRob Clark static void a3xx_destroy(struct msm_gpu *gpu) 257*7198e6b0SRob Clark { 258*7198e6b0SRob Clark struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 259*7198e6b0SRob Clark struct a3xx_gpu *a3xx_gpu = to_a3xx_gpu(adreno_gpu); 260*7198e6b0SRob Clark 261*7198e6b0SRob Clark DBG("%s", gpu->name); 262*7198e6b0SRob Clark 263*7198e6b0SRob Clark adreno_gpu_cleanup(adreno_gpu); 264*7198e6b0SRob Clark put_device(&a3xx_gpu->pdev->dev); 265*7198e6b0SRob Clark kfree(a3xx_gpu); 266*7198e6b0SRob Clark } 267*7198e6b0SRob Clark 268*7198e6b0SRob Clark static void a3xx_idle(struct msm_gpu *gpu) 269*7198e6b0SRob Clark { 270*7198e6b0SRob Clark unsigned long t; 271*7198e6b0SRob Clark 272*7198e6b0SRob Clark /* wait for ringbuffer to drain: */ 273*7198e6b0SRob Clark adreno_idle(gpu); 274*7198e6b0SRob Clark 275*7198e6b0SRob Clark t = jiffies + ADRENO_IDLE_TIMEOUT; 276*7198e6b0SRob Clark 277*7198e6b0SRob Clark /* then wait for GPU to finish: */ 278*7198e6b0SRob Clark do { 279*7198e6b0SRob Clark uint32_t rbbm_status = gpu_read(gpu, REG_A3XX_RBBM_STATUS); 280*7198e6b0SRob Clark if (!(rbbm_status & A3XX_RBBM_STATUS_GPU_BUSY)) 281*7198e6b0SRob Clark return; 282*7198e6b0SRob Clark } while(time_before(jiffies, t)); 283*7198e6b0SRob Clark 284*7198e6b0SRob Clark DRM_ERROR("timeout waiting for %s to idle!\n", gpu->name); 285*7198e6b0SRob Clark 286*7198e6b0SRob Clark /* TODO maybe we need to reset GPU here to recover from hang? */ 287*7198e6b0SRob Clark } 288*7198e6b0SRob Clark 289*7198e6b0SRob Clark static irqreturn_t a3xx_irq(struct msm_gpu *gpu) 290*7198e6b0SRob Clark { 291*7198e6b0SRob Clark uint32_t status; 292*7198e6b0SRob Clark 293*7198e6b0SRob Clark status = gpu_read(gpu, REG_A3XX_RBBM_INT_0_STATUS); 294*7198e6b0SRob Clark DBG("%s: %08x", gpu->name, status); 295*7198e6b0SRob Clark 296*7198e6b0SRob Clark // TODO 297*7198e6b0SRob Clark 298*7198e6b0SRob Clark gpu_write(gpu, REG_A3XX_RBBM_INT_CLEAR_CMD, status); 299*7198e6b0SRob Clark 300*7198e6b0SRob Clark msm_gpu_retire(gpu); 301*7198e6b0SRob Clark 302*7198e6b0SRob Clark return IRQ_HANDLED; 303*7198e6b0SRob Clark } 304*7198e6b0SRob Clark 305*7198e6b0SRob Clark #ifdef CONFIG_DEBUG_FS 306*7198e6b0SRob Clark static const unsigned int a3xx_registers[] = { 307*7198e6b0SRob Clark 0x0000, 0x0002, 0x0010, 0x0012, 0x0018, 0x0018, 0x0020, 0x0027, 308*7198e6b0SRob Clark 0x0029, 0x002b, 0x002e, 0x0033, 0x0040, 0x0042, 0x0050, 0x005c, 309*7198e6b0SRob Clark 0x0060, 0x006c, 0x0080, 0x0082, 0x0084, 0x0088, 0x0090, 0x00e5, 310*7198e6b0SRob Clark 0x00ea, 0x00ed, 0x0100, 0x0100, 0x0110, 0x0123, 0x01c0, 0x01c1, 311*7198e6b0SRob Clark 0x01c3, 0x01c5, 0x01c7, 0x01c7, 0x01d5, 0x01d9, 0x01dc, 0x01dd, 312*7198e6b0SRob Clark 0x01ea, 0x01ea, 0x01ee, 0x01f1, 0x01f5, 0x01f5, 0x01fc, 0x01ff, 313*7198e6b0SRob Clark 0x0440, 0x0440, 0x0443, 0x0443, 0x0445, 0x0445, 0x044d, 0x044f, 314*7198e6b0SRob Clark 0x0452, 0x0452, 0x0454, 0x046f, 0x047c, 0x047c, 0x047f, 0x047f, 315*7198e6b0SRob Clark 0x0578, 0x057f, 0x0600, 0x0602, 0x0605, 0x0607, 0x060a, 0x060e, 316*7198e6b0SRob Clark 0x0612, 0x0614, 0x0c01, 0x0c02, 0x0c06, 0x0c1d, 0x0c3d, 0x0c3f, 317*7198e6b0SRob Clark 0x0c48, 0x0c4b, 0x0c80, 0x0c80, 0x0c88, 0x0c8b, 0x0ca0, 0x0cb7, 318*7198e6b0SRob Clark 0x0cc0, 0x0cc1, 0x0cc6, 0x0cc7, 0x0ce4, 0x0ce5, 0x0e00, 0x0e05, 319*7198e6b0SRob Clark 0x0e0c, 0x0e0c, 0x0e22, 0x0e23, 0x0e41, 0x0e45, 0x0e64, 0x0e65, 320*7198e6b0SRob Clark 0x0e80, 0x0e82, 0x0e84, 0x0e89, 0x0ea0, 0x0ea1, 0x0ea4, 0x0ea7, 321*7198e6b0SRob Clark 0x0ec4, 0x0ecb, 0x0ee0, 0x0ee0, 0x0f00, 0x0f01, 0x0f03, 0x0f09, 322*7198e6b0SRob Clark 0x2040, 0x2040, 0x2044, 0x2044, 0x2048, 0x204d, 0x2068, 0x2069, 323*7198e6b0SRob Clark 0x206c, 0x206d, 0x2070, 0x2070, 0x2072, 0x2072, 0x2074, 0x2075, 324*7198e6b0SRob Clark 0x2079, 0x207a, 0x20c0, 0x20d3, 0x20e4, 0x20ef, 0x2100, 0x2109, 325*7198e6b0SRob Clark 0x210c, 0x210c, 0x210e, 0x210e, 0x2110, 0x2111, 0x2114, 0x2115, 326*7198e6b0SRob Clark 0x21e4, 0x21e4, 0x21ea, 0x21ea, 0x21ec, 0x21ed, 0x21f0, 0x21f0, 327*7198e6b0SRob Clark 0x2200, 0x2212, 0x2214, 0x2217, 0x221a, 0x221a, 0x2240, 0x227e, 328*7198e6b0SRob Clark 0x2280, 0x228b, 0x22c0, 0x22c0, 0x22c4, 0x22ce, 0x22d0, 0x22d8, 329*7198e6b0SRob Clark 0x22df, 0x22e6, 0x22e8, 0x22e9, 0x22ec, 0x22ec, 0x22f0, 0x22f7, 330*7198e6b0SRob Clark 0x22ff, 0x22ff, 0x2340, 0x2343, 0x2348, 0x2349, 0x2350, 0x2356, 331*7198e6b0SRob Clark 0x2360, 0x2360, 0x2440, 0x2440, 0x2444, 0x2444, 0x2448, 0x244d, 332*7198e6b0SRob Clark 0x2468, 0x2469, 0x246c, 0x246d, 0x2470, 0x2470, 0x2472, 0x2472, 333*7198e6b0SRob Clark 0x2474, 0x2475, 0x2479, 0x247a, 0x24c0, 0x24d3, 0x24e4, 0x24ef, 334*7198e6b0SRob Clark 0x2500, 0x2509, 0x250c, 0x250c, 0x250e, 0x250e, 0x2510, 0x2511, 335*7198e6b0SRob Clark 0x2514, 0x2515, 0x25e4, 0x25e4, 0x25ea, 0x25ea, 0x25ec, 0x25ed, 336*7198e6b0SRob Clark 0x25f0, 0x25f0, 0x2600, 0x2612, 0x2614, 0x2617, 0x261a, 0x261a, 337*7198e6b0SRob Clark 0x2640, 0x267e, 0x2680, 0x268b, 0x26c0, 0x26c0, 0x26c4, 0x26ce, 338*7198e6b0SRob Clark 0x26d0, 0x26d8, 0x26df, 0x26e6, 0x26e8, 0x26e9, 0x26ec, 0x26ec, 339*7198e6b0SRob Clark 0x26f0, 0x26f7, 0x26ff, 0x26ff, 0x2740, 0x2743, 0x2748, 0x2749, 340*7198e6b0SRob Clark 0x2750, 0x2756, 0x2760, 0x2760, 0x300c, 0x300e, 0x301c, 0x301d, 341*7198e6b0SRob Clark 0x302a, 0x302a, 0x302c, 0x302d, 0x3030, 0x3031, 0x3034, 0x3036, 342*7198e6b0SRob Clark 0x303c, 0x303c, 0x305e, 0x305f, 343*7198e6b0SRob Clark }; 344*7198e6b0SRob Clark 345*7198e6b0SRob Clark static void a3xx_show(struct msm_gpu *gpu, struct seq_file *m) 346*7198e6b0SRob Clark { 347*7198e6b0SRob Clark int i; 348*7198e6b0SRob Clark 349*7198e6b0SRob Clark adreno_show(gpu, m); 350*7198e6b0SRob Clark seq_printf(m, "status: %08x\n", 351*7198e6b0SRob Clark gpu_read(gpu, REG_A3XX_RBBM_STATUS)); 352*7198e6b0SRob Clark 353*7198e6b0SRob Clark /* dump these out in a form that can be parsed by demsm: */ 354*7198e6b0SRob Clark seq_printf(m, "IO:region %s 00000000 00020000\n", gpu->name); 355*7198e6b0SRob Clark for (i = 0; i < ARRAY_SIZE(a3xx_registers); i += 2) { 356*7198e6b0SRob Clark uint32_t start = a3xx_registers[i]; 357*7198e6b0SRob Clark uint32_t end = a3xx_registers[i+1]; 358*7198e6b0SRob Clark uint32_t addr; 359*7198e6b0SRob Clark 360*7198e6b0SRob Clark for (addr = start; addr <= end; addr++) { 361*7198e6b0SRob Clark uint32_t val = gpu_read(gpu, addr); 362*7198e6b0SRob Clark seq_printf(m, "IO:R %08x %08x\n", addr<<2, val); 363*7198e6b0SRob Clark } 364*7198e6b0SRob Clark } 365*7198e6b0SRob Clark } 366*7198e6b0SRob Clark #endif 367*7198e6b0SRob Clark 368*7198e6b0SRob Clark static const struct adreno_gpu_funcs funcs = { 369*7198e6b0SRob Clark .base = { 370*7198e6b0SRob Clark .get_param = adreno_get_param, 371*7198e6b0SRob Clark .hw_init = a3xx_hw_init, 372*7198e6b0SRob Clark .pm_suspend = msm_gpu_pm_suspend, 373*7198e6b0SRob Clark .pm_resume = msm_gpu_pm_resume, 374*7198e6b0SRob Clark .last_fence = adreno_last_fence, 375*7198e6b0SRob Clark .submit = adreno_submit, 376*7198e6b0SRob Clark .flush = adreno_flush, 377*7198e6b0SRob Clark .idle = a3xx_idle, 378*7198e6b0SRob Clark .irq = a3xx_irq, 379*7198e6b0SRob Clark .destroy = a3xx_destroy, 380*7198e6b0SRob Clark #ifdef CONFIG_DEBUG_FS 381*7198e6b0SRob Clark .show = a3xx_show, 382*7198e6b0SRob Clark #endif 383*7198e6b0SRob Clark }, 384*7198e6b0SRob Clark }; 385*7198e6b0SRob Clark 386*7198e6b0SRob Clark struct msm_gpu *a3xx_gpu_init(struct drm_device *dev) 387*7198e6b0SRob Clark { 388*7198e6b0SRob Clark struct a3xx_gpu *a3xx_gpu = NULL; 389*7198e6b0SRob Clark struct msm_gpu *gpu; 390*7198e6b0SRob Clark struct platform_device *pdev = a3xx_pdev; 391*7198e6b0SRob Clark struct adreno_platform_config *config; 392*7198e6b0SRob Clark int ret; 393*7198e6b0SRob Clark 394*7198e6b0SRob Clark if (!pdev) { 395*7198e6b0SRob Clark dev_err(dev->dev, "no a3xx device\n"); 396*7198e6b0SRob Clark ret = -ENXIO; 397*7198e6b0SRob Clark goto fail; 398*7198e6b0SRob Clark } 399*7198e6b0SRob Clark 400*7198e6b0SRob Clark config = pdev->dev.platform_data; 401*7198e6b0SRob Clark 402*7198e6b0SRob Clark a3xx_gpu = kzalloc(sizeof(*a3xx_gpu), GFP_KERNEL); 403*7198e6b0SRob Clark if (!a3xx_gpu) { 404*7198e6b0SRob Clark ret = -ENOMEM; 405*7198e6b0SRob Clark goto fail; 406*7198e6b0SRob Clark } 407*7198e6b0SRob Clark 408*7198e6b0SRob Clark gpu = &a3xx_gpu->base.base; 409*7198e6b0SRob Clark 410*7198e6b0SRob Clark get_device(&pdev->dev); 411*7198e6b0SRob Clark a3xx_gpu->pdev = pdev; 412*7198e6b0SRob Clark 413*7198e6b0SRob Clark gpu->fast_rate = config->fast_rate; 414*7198e6b0SRob Clark gpu->slow_rate = config->slow_rate; 415*7198e6b0SRob Clark gpu->bus_freq = config->bus_freq; 416*7198e6b0SRob Clark 417*7198e6b0SRob Clark DBG("fast_rate=%u, slow_rate=%u, bus_freq=%u", 418*7198e6b0SRob Clark gpu->fast_rate, gpu->slow_rate, gpu->bus_freq); 419*7198e6b0SRob Clark 420*7198e6b0SRob Clark ret = adreno_gpu_init(dev, pdev, &a3xx_gpu->base, 421*7198e6b0SRob Clark &funcs, config->rev); 422*7198e6b0SRob Clark if (ret) 423*7198e6b0SRob Clark goto fail; 424*7198e6b0SRob Clark 425*7198e6b0SRob Clark return &a3xx_gpu->base.base; 426*7198e6b0SRob Clark 427*7198e6b0SRob Clark fail: 428*7198e6b0SRob Clark if (a3xx_gpu) 429*7198e6b0SRob Clark a3xx_destroy(&a3xx_gpu->base.base); 430*7198e6b0SRob Clark 431*7198e6b0SRob Clark return ERR_PTR(ret); 432*7198e6b0SRob Clark } 433*7198e6b0SRob Clark 434*7198e6b0SRob Clark /* 435*7198e6b0SRob Clark * The a3xx device: 436*7198e6b0SRob Clark */ 437*7198e6b0SRob Clark 438*7198e6b0SRob Clark static int a3xx_probe(struct platform_device *pdev) 439*7198e6b0SRob Clark { 440*7198e6b0SRob Clark static struct adreno_platform_config config = {}; 441*7198e6b0SRob Clark #ifdef CONFIG_OF 442*7198e6b0SRob Clark /* TODO */ 443*7198e6b0SRob Clark #else 444*7198e6b0SRob Clark uint32_t version = socinfo_get_version(); 445*7198e6b0SRob Clark if (cpu_is_apq8064ab()) { 446*7198e6b0SRob Clark config.fast_rate = 450000000; 447*7198e6b0SRob Clark config.slow_rate = 27000000; 448*7198e6b0SRob Clark config.bus_freq = 4; 449*7198e6b0SRob Clark config.rev = ADRENO_REV(3, 2, 1, 0); 450*7198e6b0SRob Clark } else if (cpu_is_apq8064() || cpu_is_msm8960ab()) { 451*7198e6b0SRob Clark config.fast_rate = 400000000; 452*7198e6b0SRob Clark config.slow_rate = 27000000; 453*7198e6b0SRob Clark config.bus_freq = 4; 454*7198e6b0SRob Clark 455*7198e6b0SRob Clark if (SOCINFO_VERSION_MAJOR(version) == 2) 456*7198e6b0SRob Clark config.rev = ADRENO_REV(3, 2, 0, 2); 457*7198e6b0SRob Clark else if ((SOCINFO_VERSION_MAJOR(version) == 1) && 458*7198e6b0SRob Clark (SOCINFO_VERSION_MINOR(version) == 1)) 459*7198e6b0SRob Clark config.rev = ADRENO_REV(3, 2, 0, 1); 460*7198e6b0SRob Clark else 461*7198e6b0SRob Clark config.rev = ADRENO_REV(3, 2, 0, 0); 462*7198e6b0SRob Clark 463*7198e6b0SRob Clark } else if (cpu_is_msm8930()) { 464*7198e6b0SRob Clark config.fast_rate = 400000000; 465*7198e6b0SRob Clark config.slow_rate = 27000000; 466*7198e6b0SRob Clark config.bus_freq = 3; 467*7198e6b0SRob Clark 468*7198e6b0SRob Clark if ((SOCINFO_VERSION_MAJOR(version) == 1) && 469*7198e6b0SRob Clark (SOCINFO_VERSION_MINOR(version) == 2)) 470*7198e6b0SRob Clark config.rev = ADRENO_REV(3, 0, 5, 2); 471*7198e6b0SRob Clark else 472*7198e6b0SRob Clark config.rev = ADRENO_REV(3, 0, 5, 0); 473*7198e6b0SRob Clark 474*7198e6b0SRob Clark } 475*7198e6b0SRob Clark #endif 476*7198e6b0SRob Clark pdev->dev.platform_data = &config; 477*7198e6b0SRob Clark a3xx_pdev = pdev; 478*7198e6b0SRob Clark return 0; 479*7198e6b0SRob Clark } 480*7198e6b0SRob Clark 481*7198e6b0SRob Clark static int a3xx_remove(struct platform_device *pdev) 482*7198e6b0SRob Clark { 483*7198e6b0SRob Clark a3xx_pdev = NULL; 484*7198e6b0SRob Clark return 0; 485*7198e6b0SRob Clark } 486*7198e6b0SRob Clark 487*7198e6b0SRob Clark static struct platform_driver a3xx_driver = { 488*7198e6b0SRob Clark .probe = a3xx_probe, 489*7198e6b0SRob Clark .remove = a3xx_remove, 490*7198e6b0SRob Clark .driver.name = "kgsl-3d0", 491*7198e6b0SRob Clark }; 492*7198e6b0SRob Clark 493*7198e6b0SRob Clark void __init a3xx_register(void) 494*7198e6b0SRob Clark { 495*7198e6b0SRob Clark platform_driver_register(&a3xx_driver); 496*7198e6b0SRob Clark } 497*7198e6b0SRob Clark 498*7198e6b0SRob Clark void __exit a3xx_unregister(void) 499*7198e6b0SRob Clark { 500*7198e6b0SRob Clark platform_driver_unregister(&a3xx_driver); 501*7198e6b0SRob Clark } 502