1/* 2 * Copyright (C) 2013 Red Hat 3 * Author: Rob Clark <robdclark@gmail.com> 4 * 5 * Copyright (c) 2014 The Linux Foundation. All rights reserved. 6 * 7 * This program is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License version 2 as published by 9 * the Free Software Foundation. 10 * 11 * This program is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 14 * more details. 15 * 16 * You should have received a copy of the GNU General Public License along with 17 * this program. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20#ifndef __ADRENO_GPU_H__ 21#define __ADRENO_GPU_H__ 22 23#include <linux/firmware.h> 24 25#include "msm_gpu.h" 26 27#include "adreno_common.xml.h" 28#include "adreno_pm4.xml.h" 29 30#define REG_ADRENO_DEFINE(_offset, _reg) [_offset] = (_reg) + 1 31/** 32 * adreno_regs: List of registers that are used in across all 33 * 3D devices. Each device type has different offset value for the same 34 * register, so an array of register offsets are declared for every device 35 * and are indexed by the enumeration values defined in this enum 36 */ 37enum adreno_regs { 38 REG_ADRENO_CP_DEBUG, 39 REG_ADRENO_CP_ME_RAM_WADDR, 40 REG_ADRENO_CP_ME_RAM_DATA, 41 REG_ADRENO_CP_PFP_UCODE_DATA, 42 REG_ADRENO_CP_PFP_UCODE_ADDR, 43 REG_ADRENO_CP_WFI_PEND_CTR, 44 REG_ADRENO_CP_RB_BASE, 45 REG_ADRENO_CP_RB_RPTR_ADDR, 46 REG_ADRENO_CP_RB_RPTR, 47 REG_ADRENO_CP_RB_WPTR, 48 REG_ADRENO_CP_PROTECT_CTRL, 49 REG_ADRENO_CP_ME_CNTL, 50 REG_ADRENO_CP_RB_CNTL, 51 REG_ADRENO_CP_IB1_BASE, 52 REG_ADRENO_CP_IB1_BUFSZ, 53 REG_ADRENO_CP_IB2_BASE, 54 REG_ADRENO_CP_IB2_BUFSZ, 55 REG_ADRENO_CP_TIMESTAMP, 56 REG_ADRENO_CP_ME_RAM_RADDR, 57 REG_ADRENO_CP_ROQ_ADDR, 58 REG_ADRENO_CP_ROQ_DATA, 59 REG_ADRENO_CP_MERCIU_ADDR, 60 REG_ADRENO_CP_MERCIU_DATA, 61 REG_ADRENO_CP_MERCIU_DATA2, 62 REG_ADRENO_CP_MEQ_ADDR, 63 REG_ADRENO_CP_MEQ_DATA, 64 REG_ADRENO_CP_HW_FAULT, 65 REG_ADRENO_CP_PROTECT_STATUS, 66 REG_ADRENO_SCRATCH_ADDR, 67 REG_ADRENO_SCRATCH_UMSK, 68 REG_ADRENO_SCRATCH_REG2, 69 REG_ADRENO_RBBM_STATUS, 70 REG_ADRENO_RBBM_PERFCTR_CTL, 71 REG_ADRENO_RBBM_PERFCTR_LOAD_CMD0, 72 REG_ADRENO_RBBM_PERFCTR_LOAD_CMD1, 73 REG_ADRENO_RBBM_PERFCTR_LOAD_CMD2, 74 REG_ADRENO_RBBM_PERFCTR_PWR_1_LO, 75 REG_ADRENO_RBBM_INT_0_MASK, 76 REG_ADRENO_RBBM_INT_0_STATUS, 77 REG_ADRENO_RBBM_AHB_ERROR_STATUS, 78 REG_ADRENO_RBBM_PM_OVERRIDE2, 79 REG_ADRENO_RBBM_AHB_CMD, 80 REG_ADRENO_RBBM_INT_CLEAR_CMD, 81 REG_ADRENO_RBBM_SW_RESET_CMD, 82 REG_ADRENO_RBBM_CLOCK_CTL, 83 REG_ADRENO_RBBM_AHB_ME_SPLIT_STATUS, 84 REG_ADRENO_RBBM_AHB_PFP_SPLIT_STATUS, 85 REG_ADRENO_VPC_DEBUG_RAM_SEL, 86 REG_ADRENO_VPC_DEBUG_RAM_READ, 87 REG_ADRENO_VSC_SIZE_ADDRESS, 88 REG_ADRENO_VFD_CONTROL_0, 89 REG_ADRENO_VFD_INDEX_MAX, 90 REG_ADRENO_SP_VS_PVT_MEM_ADDR_REG, 91 REG_ADRENO_SP_FS_PVT_MEM_ADDR_REG, 92 REG_ADRENO_SP_VS_OBJ_START_REG, 93 REG_ADRENO_SP_FS_OBJ_START_REG, 94 REG_ADRENO_PA_SC_AA_CONFIG, 95 REG_ADRENO_SQ_GPR_MANAGEMENT, 96 REG_ADRENO_SQ_INST_STORE_MANAGMENT, 97 REG_ADRENO_TP0_CHICKEN, 98 REG_ADRENO_RBBM_RBBM_CTL, 99 REG_ADRENO_UCHE_INVALIDATE0, 100 REG_ADRENO_RBBM_PERFCTR_LOAD_VALUE_LO, 101 REG_ADRENO_RBBM_PERFCTR_LOAD_VALUE_HI, 102 REG_ADRENO_REGISTER_MAX, 103}; 104 105struct adreno_rev { 106 uint8_t core; 107 uint8_t major; 108 uint8_t minor; 109 uint8_t patchid; 110}; 111 112#define ADRENO_REV(core, major, minor, patchid) \ 113 ((struct adreno_rev){ core, major, minor, patchid }) 114 115struct adreno_gpu_funcs { 116 struct msm_gpu_funcs base; 117}; 118 119struct adreno_info { 120 struct adreno_rev rev; 121 uint32_t revn; 122 const char *name; 123 const char *pm4fw, *pfpfw; 124 uint32_t gmem; 125 struct msm_gpu *(*init)(struct drm_device *dev); 126}; 127 128const struct adreno_info *adreno_info(struct adreno_rev rev); 129 130struct adreno_rbmemptrs { 131 volatile uint32_t rptr; 132 volatile uint32_t wptr; 133 volatile uint32_t fence; 134}; 135 136struct adreno_gpu { 137 struct msm_gpu base; 138 struct adreno_rev rev; 139 const struct adreno_info *info; 140 uint32_t gmem; /* actual gmem size */ 141 uint32_t revn; /* numeric revision name */ 142 const struct adreno_gpu_funcs *funcs; 143 144 /* interesting register offsets to dump: */ 145 const unsigned int *registers; 146 147 /* firmware: */ 148 const struct firmware *pm4, *pfp; 149 150 /* ringbuffer rptr/wptr: */ 151 // TODO should this be in msm_ringbuffer? I think it would be 152 // different for z180.. 153 struct adreno_rbmemptrs *memptrs; 154 struct drm_gem_object *memptrs_bo; 155 uint32_t memptrs_iova; 156 157 /* 158 * Register offsets are different between some GPUs. 159 * GPU specific offsets will be exported by GPU specific 160 * code (a3xx_gpu.c) and stored in this common location. 161 */ 162 const unsigned int *reg_offsets; 163}; 164#define to_adreno_gpu(x) container_of(x, struct adreno_gpu, base) 165 166/* platform config data (ie. from DT, or pdata) */ 167struct adreno_platform_config { 168 struct adreno_rev rev; 169 uint32_t fast_rate, slow_rate, bus_freq; 170#ifdef CONFIG_MSM_BUS_SCALING 171 struct msm_bus_scale_pdata *bus_scale_table; 172#endif 173}; 174 175#define ADRENO_IDLE_TIMEOUT msecs_to_jiffies(1000) 176 177#define spin_until(X) ({ \ 178 int __ret = -ETIMEDOUT; \ 179 unsigned long __t = jiffies + ADRENO_IDLE_TIMEOUT; \ 180 do { \ 181 if (X) { \ 182 __ret = 0; \ 183 break; \ 184 } \ 185 } while (time_before(jiffies, __t)); \ 186 __ret; \ 187}) 188 189 190static inline bool adreno_is_a3xx(struct adreno_gpu *gpu) 191{ 192 return (gpu->revn >= 300) && (gpu->revn < 400); 193} 194 195static inline bool adreno_is_a305(struct adreno_gpu *gpu) 196{ 197 return gpu->revn == 305; 198} 199 200static inline bool adreno_is_a320(struct adreno_gpu *gpu) 201{ 202 return gpu->revn == 320; 203} 204 205static inline bool adreno_is_a330(struct adreno_gpu *gpu) 206{ 207 return gpu->revn == 330; 208} 209 210static inline bool adreno_is_a330v2(struct adreno_gpu *gpu) 211{ 212 return adreno_is_a330(gpu) && (gpu->rev.patchid > 0); 213} 214 215static inline bool adreno_is_a4xx(struct adreno_gpu *gpu) 216{ 217 return (gpu->revn >= 400) && (gpu->revn < 500); 218} 219 220static inline int adreno_is_a420(struct adreno_gpu *gpu) 221{ 222 return gpu->revn == 420; 223} 224 225int adreno_get_param(struct msm_gpu *gpu, uint32_t param, uint64_t *value); 226int adreno_hw_init(struct msm_gpu *gpu); 227uint32_t adreno_last_fence(struct msm_gpu *gpu); 228void adreno_recover(struct msm_gpu *gpu); 229int adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit, 230 struct msm_file_private *ctx); 231void adreno_flush(struct msm_gpu *gpu); 232void adreno_idle(struct msm_gpu *gpu); 233#ifdef CONFIG_DEBUG_FS 234void adreno_show(struct msm_gpu *gpu, struct seq_file *m); 235#endif 236void adreno_dump(struct msm_gpu *gpu); 237void adreno_wait_ring(struct msm_gpu *gpu, uint32_t ndwords); 238 239int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, 240 struct adreno_gpu *gpu, const struct adreno_gpu_funcs *funcs); 241void adreno_gpu_cleanup(struct adreno_gpu *gpu); 242 243 244/* ringbuffer helpers (the parts that are adreno specific) */ 245 246static inline void 247OUT_PKT0(struct msm_ringbuffer *ring, uint16_t regindx, uint16_t cnt) 248{ 249 adreno_wait_ring(ring->gpu, cnt+1); 250 OUT_RING(ring, CP_TYPE0_PKT | ((cnt-1) << 16) | (regindx & 0x7FFF)); 251} 252 253/* no-op packet: */ 254static inline void 255OUT_PKT2(struct msm_ringbuffer *ring) 256{ 257 adreno_wait_ring(ring->gpu, 1); 258 OUT_RING(ring, CP_TYPE2_PKT); 259} 260 261static inline void 262OUT_PKT3(struct msm_ringbuffer *ring, uint8_t opcode, uint16_t cnt) 263{ 264 adreno_wait_ring(ring->gpu, cnt+1); 265 OUT_RING(ring, CP_TYPE3_PKT | ((cnt-1) << 16) | ((opcode & 0xFF) << 8)); 266} 267 268/* 269 * adreno_checkreg_off() - Checks the validity of a register enum 270 * @gpu: Pointer to struct adreno_gpu 271 * @offset_name: The register enum that is checked 272 */ 273static inline bool adreno_reg_check(struct adreno_gpu *gpu, 274 enum adreno_regs offset_name) 275{ 276 if (offset_name >= REG_ADRENO_REGISTER_MAX || 277 !gpu->reg_offsets[offset_name]) { 278 BUG(); 279 } 280 return true; 281} 282 283static inline u32 adreno_gpu_read(struct adreno_gpu *gpu, 284 enum adreno_regs offset_name) 285{ 286 u32 reg = gpu->reg_offsets[offset_name]; 287 u32 val = 0; 288 if(adreno_reg_check(gpu,offset_name)) 289 val = gpu_read(&gpu->base, reg - 1); 290 return val; 291} 292 293static inline void adreno_gpu_write(struct adreno_gpu *gpu, 294 enum adreno_regs offset_name, u32 data) 295{ 296 u32 reg = gpu->reg_offsets[offset_name]; 297 if(adreno_reg_check(gpu, offset_name)) 298 gpu_write(&gpu->base, reg - 1, data); 299} 300 301#endif /* __ADRENO_GPU_H__ */ 302