a5xx_gpu.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888
  1. /* Copyright (c) 2016 The Linux Foundation. All rights reserved.
  2. *
  3. * This program is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License version 2 and
  5. * only version 2 as published by the Free Software Foundation.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. *
  12. */
  13. #include "msm_gem.h"
  14. #include "a5xx_gpu.h"
  15. extern bool hang_debug;
  16. static void a5xx_dump(struct msm_gpu *gpu);
  17. static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
  18. struct msm_file_private *ctx)
  19. {
  20. struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
  21. struct msm_drm_private *priv = gpu->dev->dev_private;
  22. struct msm_ringbuffer *ring = gpu->rb;
  23. unsigned int i, ibs = 0;
  24. for (i = 0; i < submit->nr_cmds; i++) {
  25. switch (submit->cmd[i].type) {
  26. case MSM_SUBMIT_CMD_IB_TARGET_BUF:
  27. break;
  28. case MSM_SUBMIT_CMD_CTX_RESTORE_BUF:
  29. if (priv->lastctx == ctx)
  30. break;
  31. case MSM_SUBMIT_CMD_BUF:
  32. OUT_PKT7(ring, CP_INDIRECT_BUFFER_PFE, 3);
  33. OUT_RING(ring, lower_32_bits(submit->cmd[i].iova));
  34. OUT_RING(ring, upper_32_bits(submit->cmd[i].iova));
  35. OUT_RING(ring, submit->cmd[i].size);
  36. ibs++;
  37. break;
  38. }
  39. }
  40. OUT_PKT4(ring, REG_A5XX_CP_SCRATCH_REG(2), 1);
  41. OUT_RING(ring, submit->fence->seqno);
  42. OUT_PKT7(ring, CP_EVENT_WRITE, 4);
  43. OUT_RING(ring, CACHE_FLUSH_TS | (1 << 31));
  44. OUT_RING(ring, lower_32_bits(rbmemptr(adreno_gpu, fence)));
  45. OUT_RING(ring, upper_32_bits(rbmemptr(adreno_gpu, fence)));
  46. OUT_RING(ring, submit->fence->seqno);
  47. gpu->funcs->flush(gpu);
  48. }
  49. struct a5xx_hwcg {
  50. u32 offset;
  51. u32 value;
  52. };
  53. static const struct a5xx_hwcg a530_hwcg[] = {
  54. {REG_A5XX_RBBM_CLOCK_CNTL_SP0, 0x02222222},
  55. {REG_A5XX_RBBM_CLOCK_CNTL_SP1, 0x02222222},
  56. {REG_A5XX_RBBM_CLOCK_CNTL_SP2, 0x02222222},
  57. {REG_A5XX_RBBM_CLOCK_CNTL_SP3, 0x02222222},
  58. {REG_A5XX_RBBM_CLOCK_CNTL2_SP0, 0x02222220},
  59. {REG_A5XX_RBBM_CLOCK_CNTL2_SP1, 0x02222220},
  60. {REG_A5XX_RBBM_CLOCK_CNTL2_SP2, 0x02222220},
  61. {REG_A5XX_RBBM_CLOCK_CNTL2_SP3, 0x02222220},
  62. {REG_A5XX_RBBM_CLOCK_HYST_SP0, 0x0000F3CF},
  63. {REG_A5XX_RBBM_CLOCK_HYST_SP1, 0x0000F3CF},
  64. {REG_A5XX_RBBM_CLOCK_HYST_SP2, 0x0000F3CF},
  65. {REG_A5XX_RBBM_CLOCK_HYST_SP3, 0x0000F3CF},
  66. {REG_A5XX_RBBM_CLOCK_DELAY_SP0, 0x00000080},
  67. {REG_A5XX_RBBM_CLOCK_DELAY_SP1, 0x00000080},
  68. {REG_A5XX_RBBM_CLOCK_DELAY_SP2, 0x00000080},
  69. {REG_A5XX_RBBM_CLOCK_DELAY_SP3, 0x00000080},
  70. {REG_A5XX_RBBM_CLOCK_CNTL_TP0, 0x22222222},
  71. {REG_A5XX_RBBM_CLOCK_CNTL_TP1, 0x22222222},
  72. {REG_A5XX_RBBM_CLOCK_CNTL_TP2, 0x22222222},
  73. {REG_A5XX_RBBM_CLOCK_CNTL_TP3, 0x22222222},
  74. {REG_A5XX_RBBM_CLOCK_CNTL2_TP0, 0x22222222},
  75. {REG_A5XX_RBBM_CLOCK_CNTL2_TP1, 0x22222222},
  76. {REG_A5XX_RBBM_CLOCK_CNTL2_TP2, 0x22222222},
  77. {REG_A5XX_RBBM_CLOCK_CNTL2_TP3, 0x22222222},
  78. {REG_A5XX_RBBM_CLOCK_CNTL3_TP0, 0x00002222},
  79. {REG_A5XX_RBBM_CLOCK_CNTL3_TP1, 0x00002222},
  80. {REG_A5XX_RBBM_CLOCK_CNTL3_TP2, 0x00002222},
  81. {REG_A5XX_RBBM_CLOCK_CNTL3_TP3, 0x00002222},
  82. {REG_A5XX_RBBM_CLOCK_HYST_TP0, 0x77777777},
  83. {REG_A5XX_RBBM_CLOCK_HYST_TP1, 0x77777777},
  84. {REG_A5XX_RBBM_CLOCK_HYST_TP2, 0x77777777},
  85. {REG_A5XX_RBBM_CLOCK_HYST_TP3, 0x77777777},
  86. {REG_A5XX_RBBM_CLOCK_HYST2_TP0, 0x77777777},
  87. {REG_A5XX_RBBM_CLOCK_HYST2_TP1, 0x77777777},
  88. {REG_A5XX_RBBM_CLOCK_HYST2_TP2, 0x77777777},
  89. {REG_A5XX_RBBM_CLOCK_HYST2_TP3, 0x77777777},
  90. {REG_A5XX_RBBM_CLOCK_HYST3_TP0, 0x00007777},
  91. {REG_A5XX_RBBM_CLOCK_HYST3_TP1, 0x00007777},
  92. {REG_A5XX_RBBM_CLOCK_HYST3_TP2, 0x00007777},
  93. {REG_A5XX_RBBM_CLOCK_HYST3_TP3, 0x00007777},
  94. {REG_A5XX_RBBM_CLOCK_DELAY_TP0, 0x11111111},
  95. {REG_A5XX_RBBM_CLOCK_DELAY_TP1, 0x11111111},
  96. {REG_A5XX_RBBM_CLOCK_DELAY_TP2, 0x11111111},
  97. {REG_A5XX_RBBM_CLOCK_DELAY_TP3, 0x11111111},
  98. {REG_A5XX_RBBM_CLOCK_DELAY2_TP0, 0x11111111},
  99. {REG_A5XX_RBBM_CLOCK_DELAY2_TP1, 0x11111111},
  100. {REG_A5XX_RBBM_CLOCK_DELAY2_TP2, 0x11111111},
  101. {REG_A5XX_RBBM_CLOCK_DELAY2_TP3, 0x11111111},
  102. {REG_A5XX_RBBM_CLOCK_DELAY3_TP0, 0x00001111},
  103. {REG_A5XX_RBBM_CLOCK_DELAY3_TP1, 0x00001111},
  104. {REG_A5XX_RBBM_CLOCK_DELAY3_TP2, 0x00001111},
  105. {REG_A5XX_RBBM_CLOCK_DELAY3_TP3, 0x00001111},
  106. {REG_A5XX_RBBM_CLOCK_CNTL_UCHE, 0x22222222},
  107. {REG_A5XX_RBBM_CLOCK_CNTL2_UCHE, 0x22222222},
  108. {REG_A5XX_RBBM_CLOCK_CNTL3_UCHE, 0x22222222},
  109. {REG_A5XX_RBBM_CLOCK_CNTL4_UCHE, 0x00222222},
  110. {REG_A5XX_RBBM_CLOCK_HYST_UCHE, 0x00444444},
  111. {REG_A5XX_RBBM_CLOCK_DELAY_UCHE, 0x00000002},
  112. {REG_A5XX_RBBM_CLOCK_CNTL_RB0, 0x22222222},
  113. {REG_A5XX_RBBM_CLOCK_CNTL_RB1, 0x22222222},
  114. {REG_A5XX_RBBM_CLOCK_CNTL_RB2, 0x22222222},
  115. {REG_A5XX_RBBM_CLOCK_CNTL_RB3, 0x22222222},
  116. {REG_A5XX_RBBM_CLOCK_CNTL2_RB0, 0x00222222},
  117. {REG_A5XX_RBBM_CLOCK_CNTL2_RB1, 0x00222222},
  118. {REG_A5XX_RBBM_CLOCK_CNTL2_RB2, 0x00222222},
  119. {REG_A5XX_RBBM_CLOCK_CNTL2_RB3, 0x00222222},
  120. {REG_A5XX_RBBM_CLOCK_CNTL_CCU0, 0x00022220},
  121. {REG_A5XX_RBBM_CLOCK_CNTL_CCU1, 0x00022220},
  122. {REG_A5XX_RBBM_CLOCK_CNTL_CCU2, 0x00022220},
  123. {REG_A5XX_RBBM_CLOCK_CNTL_CCU3, 0x00022220},
  124. {REG_A5XX_RBBM_CLOCK_CNTL_RAC, 0x05522222},
  125. {REG_A5XX_RBBM_CLOCK_CNTL2_RAC, 0x00505555},
  126. {REG_A5XX_RBBM_CLOCK_HYST_RB_CCU0, 0x04040404},
  127. {REG_A5XX_RBBM_CLOCK_HYST_RB_CCU1, 0x04040404},
  128. {REG_A5XX_RBBM_CLOCK_HYST_RB_CCU2, 0x04040404},
  129. {REG_A5XX_RBBM_CLOCK_HYST_RB_CCU3, 0x04040404},
  130. {REG_A5XX_RBBM_CLOCK_HYST_RAC, 0x07444044},
  131. {REG_A5XX_RBBM_CLOCK_DELAY_RB_CCU_L1_0, 0x00000002},
  132. {REG_A5XX_RBBM_CLOCK_DELAY_RB_CCU_L1_1, 0x00000002},
  133. {REG_A5XX_RBBM_CLOCK_DELAY_RB_CCU_L1_2, 0x00000002},
  134. {REG_A5XX_RBBM_CLOCK_DELAY_RB_CCU_L1_3, 0x00000002},
  135. {REG_A5XX_RBBM_CLOCK_DELAY_RAC, 0x00010011},
  136. {REG_A5XX_RBBM_CLOCK_CNTL_TSE_RAS_RBBM, 0x04222222},
  137. {REG_A5XX_RBBM_CLOCK_MODE_GPC, 0x02222222},
  138. {REG_A5XX_RBBM_CLOCK_MODE_VFD, 0x00002222},
  139. {REG_A5XX_RBBM_CLOCK_HYST_TSE_RAS_RBBM, 0x00000000},
  140. {REG_A5XX_RBBM_CLOCK_HYST_GPC, 0x04104004},
  141. {REG_A5XX_RBBM_CLOCK_HYST_VFD, 0x00000000},
  142. {REG_A5XX_RBBM_CLOCK_DELAY_HLSQ, 0x00000000},
  143. {REG_A5XX_RBBM_CLOCK_DELAY_TSE_RAS_RBBM, 0x00004000},
  144. {REG_A5XX_RBBM_CLOCK_DELAY_GPC, 0x00000200},
  145. {REG_A5XX_RBBM_CLOCK_DELAY_VFD, 0x00002222}
  146. };
  147. static const struct {
  148. int (*test)(struct adreno_gpu *gpu);
  149. const struct a5xx_hwcg *regs;
  150. unsigned int count;
  151. } a5xx_hwcg_regs[] = {
  152. { adreno_is_a530, a530_hwcg, ARRAY_SIZE(a530_hwcg), },
  153. };
  154. static void _a5xx_enable_hwcg(struct msm_gpu *gpu,
  155. const struct a5xx_hwcg *regs, unsigned int count)
  156. {
  157. unsigned int i;
  158. for (i = 0; i < count; i++)
  159. gpu_write(gpu, regs[i].offset, regs[i].value);
  160. gpu_write(gpu, REG_A5XX_RBBM_CLOCK_CNTL, 0xAAA8AA00);
  161. gpu_write(gpu, REG_A5XX_RBBM_ISDB_CNT, 0x182);
  162. }
  163. static void a5xx_enable_hwcg(struct msm_gpu *gpu)
  164. {
  165. struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
  166. unsigned int i;
  167. for (i = 0; i < ARRAY_SIZE(a5xx_hwcg_regs); i++) {
  168. if (a5xx_hwcg_regs[i].test(adreno_gpu)) {
  169. _a5xx_enable_hwcg(gpu, a5xx_hwcg_regs[i].regs,
  170. a5xx_hwcg_regs[i].count);
  171. return;
  172. }
  173. }
  174. }
  175. static int a5xx_me_init(struct msm_gpu *gpu)
  176. {
  177. struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
  178. struct msm_ringbuffer *ring = gpu->rb;
  179. OUT_PKT7(ring, CP_ME_INIT, 8);
  180. OUT_RING(ring, 0x0000002F);
  181. /* Enable multiple hardware contexts */
  182. OUT_RING(ring, 0x00000003);
  183. /* Enable error detection */
  184. OUT_RING(ring, 0x20000000);
  185. /* Don't enable header dump */
  186. OUT_RING(ring, 0x00000000);
  187. OUT_RING(ring, 0x00000000);
  188. /* Specify workarounds for various microcode issues */
  189. if (adreno_is_a530(adreno_gpu)) {
  190. /* Workaround for token end syncs
  191. * Force a WFI after every direct-render 3D mode draw and every
  192. * 2D mode 3 draw
  193. */
  194. OUT_RING(ring, 0x0000000B);
  195. } else {
  196. /* No workarounds enabled */
  197. OUT_RING(ring, 0x00000000);
  198. }
  199. OUT_RING(ring, 0x00000000);
  200. OUT_RING(ring, 0x00000000);
  201. gpu->funcs->flush(gpu);
  202. return gpu->funcs->idle(gpu) ? 0 : -EINVAL;
  203. }
  204. static struct drm_gem_object *a5xx_ucode_load_bo(struct msm_gpu *gpu,
  205. const struct firmware *fw, u64 *iova)
  206. {
  207. struct drm_device *drm = gpu->dev;
  208. struct drm_gem_object *bo;
  209. void *ptr;
  210. mutex_lock(&drm->struct_mutex);
  211. bo = msm_gem_new(drm, fw->size - 4, MSM_BO_UNCACHED);
  212. mutex_unlock(&drm->struct_mutex);
  213. if (IS_ERR(bo))
  214. return bo;
  215. ptr = msm_gem_get_vaddr(bo);
  216. if (!ptr) {
  217. drm_gem_object_unreference_unlocked(bo);
  218. return ERR_PTR(-ENOMEM);
  219. }
  220. if (iova) {
  221. int ret = msm_gem_get_iova(bo, gpu->id, iova);
  222. if (ret) {
  223. drm_gem_object_unreference_unlocked(bo);
  224. return ERR_PTR(ret);
  225. }
  226. }
  227. memcpy(ptr, &fw->data[4], fw->size - 4);
  228. msm_gem_put_vaddr(bo);
  229. return bo;
  230. }
  231. static int a5xx_ucode_init(struct msm_gpu *gpu)
  232. {
  233. struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
  234. struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu);
  235. int ret;
  236. if (!a5xx_gpu->pm4_bo) {
  237. a5xx_gpu->pm4_bo = a5xx_ucode_load_bo(gpu, adreno_gpu->pm4,
  238. &a5xx_gpu->pm4_iova);
  239. if (IS_ERR(a5xx_gpu->pm4_bo)) {
  240. ret = PTR_ERR(a5xx_gpu->pm4_bo);
  241. a5xx_gpu->pm4_bo = NULL;
  242. dev_err(gpu->dev->dev, "could not allocate PM4: %d\n",
  243. ret);
  244. return ret;
  245. }
  246. }
  247. if (!a5xx_gpu->pfp_bo) {
  248. a5xx_gpu->pfp_bo = a5xx_ucode_load_bo(gpu, adreno_gpu->pfp,
  249. &a5xx_gpu->pfp_iova);
  250. if (IS_ERR(a5xx_gpu->pfp_bo)) {
  251. ret = PTR_ERR(a5xx_gpu->pfp_bo);
  252. a5xx_gpu->pfp_bo = NULL;
  253. dev_err(gpu->dev->dev, "could not allocate PFP: %d\n",
  254. ret);
  255. return ret;
  256. }
  257. }
  258. gpu_write64(gpu, REG_A5XX_CP_ME_INSTR_BASE_LO,
  259. REG_A5XX_CP_ME_INSTR_BASE_HI, a5xx_gpu->pm4_iova);
  260. gpu_write64(gpu, REG_A5XX_CP_PFP_INSTR_BASE_LO,
  261. REG_A5XX_CP_PFP_INSTR_BASE_HI, a5xx_gpu->pfp_iova);
  262. return 0;
  263. }
  264. #define A5XX_INT_MASK (A5XX_RBBM_INT_0_MASK_RBBM_AHB_ERROR | \
  265. A5XX_RBBM_INT_0_MASK_RBBM_TRANSFER_TIMEOUT | \
  266. A5XX_RBBM_INT_0_MASK_RBBM_ME_MS_TIMEOUT | \
  267. A5XX_RBBM_INT_0_MASK_RBBM_PFP_MS_TIMEOUT | \
  268. A5XX_RBBM_INT_0_MASK_RBBM_ETS_MS_TIMEOUT | \
  269. A5XX_RBBM_INT_0_MASK_RBBM_ATB_ASYNC_OVERFLOW | \
  270. A5XX_RBBM_INT_0_MASK_CP_HW_ERROR | \
  271. A5XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS | \
  272. A5XX_RBBM_INT_0_MASK_UCHE_OOB_ACCESS | \
  273. A5XX_RBBM_INT_0_MASK_GPMU_VOLTAGE_DROOP)
  274. static int a5xx_hw_init(struct msm_gpu *gpu)
  275. {
  276. struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
  277. int ret;
  278. gpu_write(gpu, REG_A5XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x00000003);
  279. /* Make all blocks contribute to the GPU BUSY perf counter */
  280. gpu_write(gpu, REG_A5XX_RBBM_PERFCTR_GPU_BUSY_MASKED, 0xFFFFFFFF);
  281. /* Enable RBBM error reporting bits */
  282. gpu_write(gpu, REG_A5XX_RBBM_AHB_CNTL0, 0x00000001);
  283. if (adreno_gpu->quirks & ADRENO_QUIRK_FAULT_DETECT_MASK) {
  284. /*
  285. * Mask out the activity signals from RB1-3 to avoid false
  286. * positives
  287. */
  288. gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL11,
  289. 0xF0000000);
  290. gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL12,
  291. 0xFFFFFFFF);
  292. gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL13,
  293. 0xFFFFFFFF);
  294. gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL14,
  295. 0xFFFFFFFF);
  296. gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL15,
  297. 0xFFFFFFFF);
  298. gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL16,
  299. 0xFFFFFFFF);
  300. gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL17,
  301. 0xFFFFFFFF);
  302. gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL18,
  303. 0xFFFFFFFF);
  304. }
  305. /* Enable fault detection */
  306. gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_INT_CNTL,
  307. (1 << 30) | 0xFFFF);
  308. /* Turn on performance counters */
  309. gpu_write(gpu, REG_A5XX_RBBM_PERFCTR_CNTL, 0x01);
  310. /* Increase VFD cache access so LRZ and other data gets evicted less */
  311. gpu_write(gpu, REG_A5XX_UCHE_CACHE_WAYS, 0x02);
  312. /* Disable L2 bypass in the UCHE */
  313. gpu_write(gpu, REG_A5XX_UCHE_TRAP_BASE_LO, 0xFFFF0000);
  314. gpu_write(gpu, REG_A5XX_UCHE_TRAP_BASE_HI, 0x0001FFFF);
  315. gpu_write(gpu, REG_A5XX_UCHE_WRITE_THRU_BASE_LO, 0xFFFF0000);
  316. gpu_write(gpu, REG_A5XX_UCHE_WRITE_THRU_BASE_HI, 0x0001FFFF);
  317. /* Set the GMEM VA range (0 to gpu->gmem) */
  318. gpu_write(gpu, REG_A5XX_UCHE_GMEM_RANGE_MIN_LO, 0x00100000);
  319. gpu_write(gpu, REG_A5XX_UCHE_GMEM_RANGE_MIN_HI, 0x00000000);
  320. gpu_write(gpu, REG_A5XX_UCHE_GMEM_RANGE_MAX_LO,
  321. 0x00100000 + adreno_gpu->gmem - 1);
  322. gpu_write(gpu, REG_A5XX_UCHE_GMEM_RANGE_MAX_HI, 0x00000000);
  323. gpu_write(gpu, REG_A5XX_CP_MEQ_THRESHOLDS, 0x40);
  324. gpu_write(gpu, REG_A5XX_CP_MERCIU_SIZE, 0x40);
  325. gpu_write(gpu, REG_A5XX_CP_ROQ_THRESHOLDS_2, 0x80000060);
  326. gpu_write(gpu, REG_A5XX_CP_ROQ_THRESHOLDS_1, 0x40201B16);
  327. gpu_write(gpu, REG_A5XX_PC_DBG_ECO_CNTL, (0x400 << 11 | 0x300 << 22));
  328. if (adreno_gpu->quirks & ADRENO_QUIRK_TWO_PASS_USE_WFI)
  329. gpu_rmw(gpu, REG_A5XX_PC_DBG_ECO_CNTL, 0, (1 << 8));
  330. gpu_write(gpu, REG_A5XX_PC_DBG_ECO_CNTL, 0xc0200100);
  331. /* Enable USE_RETENTION_FLOPS */
  332. gpu_write(gpu, REG_A5XX_CP_CHICKEN_DBG, 0x02000000);
  333. /* Enable ME/PFP split notification */
  334. gpu_write(gpu, REG_A5XX_RBBM_AHB_CNTL1, 0xA6FFFFFF);
  335. /* Enable HWCG */
  336. a5xx_enable_hwcg(gpu);
  337. gpu_write(gpu, REG_A5XX_RBBM_AHB_CNTL2, 0x0000003F);
  338. /* Set the highest bank bit */
  339. gpu_write(gpu, REG_A5XX_TPL1_MODE_CNTL, 2 << 7);
  340. gpu_write(gpu, REG_A5XX_RB_MODE_CNTL, 2 << 1);
  341. /* Protect registers from the CP */
  342. gpu_write(gpu, REG_A5XX_CP_PROTECT_CNTL, 0x00000007);
  343. /* RBBM */
  344. gpu_write(gpu, REG_A5XX_CP_PROTECT(0), ADRENO_PROTECT_RW(0x04, 4));
  345. gpu_write(gpu, REG_A5XX_CP_PROTECT(1), ADRENO_PROTECT_RW(0x08, 8));
  346. gpu_write(gpu, REG_A5XX_CP_PROTECT(2), ADRENO_PROTECT_RW(0x10, 16));
  347. gpu_write(gpu, REG_A5XX_CP_PROTECT(3), ADRENO_PROTECT_RW(0x20, 32));
  348. gpu_write(gpu, REG_A5XX_CP_PROTECT(4), ADRENO_PROTECT_RW(0x40, 64));
  349. gpu_write(gpu, REG_A5XX_CP_PROTECT(5), ADRENO_PROTECT_RW(0x80, 64));
  350. /* Content protect */
  351. gpu_write(gpu, REG_A5XX_CP_PROTECT(6),
  352. ADRENO_PROTECT_RW(REG_A5XX_RBBM_SECVID_TSB_TRUSTED_BASE_LO,
  353. 16));
  354. gpu_write(gpu, REG_A5XX_CP_PROTECT(7),
  355. ADRENO_PROTECT_RW(REG_A5XX_RBBM_SECVID_TRUST_CNTL, 2));
  356. /* CP */
  357. gpu_write(gpu, REG_A5XX_CP_PROTECT(8), ADRENO_PROTECT_RW(0x800, 64));
  358. gpu_write(gpu, REG_A5XX_CP_PROTECT(9), ADRENO_PROTECT_RW(0x840, 8));
  359. gpu_write(gpu, REG_A5XX_CP_PROTECT(10), ADRENO_PROTECT_RW(0x880, 32));
  360. gpu_write(gpu, REG_A5XX_CP_PROTECT(11), ADRENO_PROTECT_RW(0xAA0, 1));
  361. /* RB */
  362. gpu_write(gpu, REG_A5XX_CP_PROTECT(12), ADRENO_PROTECT_RW(0xCC0, 1));
  363. gpu_write(gpu, REG_A5XX_CP_PROTECT(13), ADRENO_PROTECT_RW(0xCF0, 2));
  364. /* VPC */
  365. gpu_write(gpu, REG_A5XX_CP_PROTECT(14), ADRENO_PROTECT_RW(0xE68, 8));
  366. gpu_write(gpu, REG_A5XX_CP_PROTECT(15), ADRENO_PROTECT_RW(0xE70, 4));
  367. /* UCHE */
  368. gpu_write(gpu, REG_A5XX_CP_PROTECT(16), ADRENO_PROTECT_RW(0xE80, 16));
  369. if (adreno_is_a530(adreno_gpu))
  370. gpu_write(gpu, REG_A5XX_CP_PROTECT(17),
  371. ADRENO_PROTECT_RW(0x10000, 0x8000));
  372. gpu_write(gpu, REG_A5XX_RBBM_SECVID_TSB_CNTL, 0);
  373. /*
  374. * Disable the trusted memory range - we don't actually supported secure
  375. * memory rendering at this point in time and we don't want to block off
  376. * part of the virtual memory space.
  377. */
  378. gpu_write64(gpu, REG_A5XX_RBBM_SECVID_TSB_TRUSTED_BASE_LO,
  379. REG_A5XX_RBBM_SECVID_TSB_TRUSTED_BASE_HI, 0x00000000);
  380. gpu_write(gpu, REG_A5XX_RBBM_SECVID_TSB_TRUSTED_SIZE, 0x00000000);
  381. /* Load the GPMU firmware before starting the HW init */
  382. a5xx_gpmu_ucode_init(gpu);
  383. ret = adreno_hw_init(gpu);
  384. if (ret)
  385. return ret;
  386. ret = a5xx_ucode_init(gpu);
  387. if (ret)
  388. return ret;
  389. /* Disable the interrupts through the initial bringup stage */
  390. gpu_write(gpu, REG_A5XX_RBBM_INT_0_MASK, A5XX_INT_MASK);
  391. /* Clear ME_HALT to start the micro engine */
  392. gpu_write(gpu, REG_A5XX_CP_PFP_ME_CNTL, 0);
  393. ret = a5xx_me_init(gpu);
  394. if (ret)
  395. return ret;
  396. ret = a5xx_power_init(gpu);
  397. if (ret)
  398. return ret;
  399. /*
  400. * Send a pipeline event stat to get misbehaving counters to start
  401. * ticking correctly
  402. */
  403. if (adreno_is_a530(adreno_gpu)) {
  404. OUT_PKT7(gpu->rb, CP_EVENT_WRITE, 1);
  405. OUT_RING(gpu->rb, 0x0F);
  406. gpu->funcs->flush(gpu);
  407. if (!gpu->funcs->idle(gpu))
  408. return -EINVAL;
  409. }
  410. /* Put the GPU into unsecure mode */
  411. gpu_write(gpu, REG_A5XX_RBBM_SECVID_TRUST_CNTL, 0x0);
  412. return 0;
  413. }
  414. static void a5xx_recover(struct msm_gpu *gpu)
  415. {
  416. int i;
  417. adreno_dump_info(gpu);
  418. for (i = 0; i < 8; i++) {
  419. printk("CP_SCRATCH_REG%d: %u\n", i,
  420. gpu_read(gpu, REG_A5XX_CP_SCRATCH_REG(i)));
  421. }
  422. if (hang_debug)
  423. a5xx_dump(gpu);
  424. gpu_write(gpu, REG_A5XX_RBBM_SW_RESET_CMD, 1);
  425. gpu_read(gpu, REG_A5XX_RBBM_SW_RESET_CMD);
  426. gpu_write(gpu, REG_A5XX_RBBM_SW_RESET_CMD, 0);
  427. adreno_recover(gpu);
  428. }
  429. static void a5xx_destroy(struct msm_gpu *gpu)
  430. {
  431. struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
  432. struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu);
  433. DBG("%s", gpu->name);
  434. if (a5xx_gpu->pm4_bo) {
  435. if (a5xx_gpu->pm4_iova)
  436. msm_gem_put_iova(a5xx_gpu->pm4_bo, gpu->id);
  437. drm_gem_object_unreference_unlocked(a5xx_gpu->pm4_bo);
  438. }
  439. if (a5xx_gpu->pfp_bo) {
  440. if (a5xx_gpu->pfp_iova)
  441. msm_gem_put_iova(a5xx_gpu->pfp_bo, gpu->id);
  442. drm_gem_object_unreference_unlocked(a5xx_gpu->pfp_bo);
  443. }
  444. if (a5xx_gpu->gpmu_bo) {
  445. if (a5xx_gpu->gpmu_bo)
  446. msm_gem_put_iova(a5xx_gpu->gpmu_bo, gpu->id);
  447. drm_gem_object_unreference_unlocked(a5xx_gpu->gpmu_bo);
  448. }
  449. adreno_gpu_cleanup(adreno_gpu);
  450. kfree(a5xx_gpu);
  451. }
  452. static inline bool _a5xx_check_idle(struct msm_gpu *gpu)
  453. {
  454. if (gpu_read(gpu, REG_A5XX_RBBM_STATUS) & ~A5XX_RBBM_STATUS_HI_BUSY)
  455. return false;
  456. /*
  457. * Nearly every abnormality ends up pausing the GPU and triggering a
  458. * fault so we can safely just watch for this one interrupt to fire
  459. */
  460. return !(gpu_read(gpu, REG_A5XX_RBBM_INT_0_STATUS) &
  461. A5XX_RBBM_INT_0_MASK_MISC_HANG_DETECT);
  462. }
  463. static bool a5xx_idle(struct msm_gpu *gpu)
  464. {
  465. /* wait for CP to drain ringbuffer: */
  466. if (!adreno_idle(gpu))
  467. return false;
  468. if (spin_until(_a5xx_check_idle(gpu))) {
  469. DRM_ERROR("%s: %ps: timeout waiting for GPU to idle: status %8.8X irq %8.8X\n",
  470. gpu->name, __builtin_return_address(0),
  471. gpu_read(gpu, REG_A5XX_RBBM_STATUS),
  472. gpu_read(gpu, REG_A5XX_RBBM_INT_0_STATUS));
  473. return false;
  474. }
  475. return true;
  476. }
  477. static void a5xx_cp_err_irq(struct msm_gpu *gpu)
  478. {
  479. u32 status = gpu_read(gpu, REG_A5XX_CP_INTERRUPT_STATUS);
  480. if (status & A5XX_CP_INT_CP_OPCODE_ERROR) {
  481. u32 val;
  482. gpu_write(gpu, REG_A5XX_CP_PFP_STAT_ADDR, 0);
  483. /*
  484. * REG_A5XX_CP_PFP_STAT_DATA is indexed, and we want index 1 so
  485. * read it twice
  486. */
  487. gpu_read(gpu, REG_A5XX_CP_PFP_STAT_DATA);
  488. val = gpu_read(gpu, REG_A5XX_CP_PFP_STAT_DATA);
  489. dev_err_ratelimited(gpu->dev->dev, "CP | opcode error | possible opcode=0x%8.8X\n",
  490. val);
  491. }
  492. if (status & A5XX_CP_INT_CP_HW_FAULT_ERROR)
  493. dev_err_ratelimited(gpu->dev->dev, "CP | HW fault | status=0x%8.8X\n",
  494. gpu_read(gpu, REG_A5XX_CP_HW_FAULT));
  495. if (status & A5XX_CP_INT_CP_DMA_ERROR)
  496. dev_err_ratelimited(gpu->dev->dev, "CP | DMA error\n");
  497. if (status & A5XX_CP_INT_CP_REGISTER_PROTECTION_ERROR) {
  498. u32 val = gpu_read(gpu, REG_A5XX_CP_PROTECT_STATUS);
  499. dev_err_ratelimited(gpu->dev->dev,
  500. "CP | protected mode error | %s | addr=0x%8.8X | status=0x%8.8X\n",
  501. val & (1 << 24) ? "WRITE" : "READ",
  502. (val & 0xFFFFF) >> 2, val);
  503. }
  504. if (status & A5XX_CP_INT_CP_AHB_ERROR) {
  505. u32 status = gpu_read(gpu, REG_A5XX_CP_AHB_FAULT);
  506. const char *access[16] = { "reserved", "reserved",
  507. "timestamp lo", "timestamp hi", "pfp read", "pfp write",
  508. "", "", "me read", "me write", "", "", "crashdump read",
  509. "crashdump write" };
  510. dev_err_ratelimited(gpu->dev->dev,
  511. "CP | AHB error | addr=%X access=%s error=%d | status=0x%8.8X\n",
  512. status & 0xFFFFF, access[(status >> 24) & 0xF],
  513. (status & (1 << 31)), status);
  514. }
  515. }
  516. static void a5xx_rbbm_err_irq(struct msm_gpu *gpu)
  517. {
  518. u32 status = gpu_read(gpu, REG_A5XX_RBBM_INT_0_STATUS);
  519. if (status & A5XX_RBBM_INT_0_MASK_RBBM_AHB_ERROR) {
  520. u32 val = gpu_read(gpu, REG_A5XX_RBBM_AHB_ERROR_STATUS);
  521. dev_err_ratelimited(gpu->dev->dev,
  522. "RBBM | AHB bus error | %s | addr=0x%X | ports=0x%X:0x%X\n",
  523. val & (1 << 28) ? "WRITE" : "READ",
  524. (val & 0xFFFFF) >> 2, (val >> 20) & 0x3,
  525. (val >> 24) & 0xF);
  526. /* Clear the error */
  527. gpu_write(gpu, REG_A5XX_RBBM_AHB_CMD, (1 << 4));
  528. }
  529. if (status & A5XX_RBBM_INT_0_MASK_RBBM_TRANSFER_TIMEOUT)
  530. dev_err_ratelimited(gpu->dev->dev, "RBBM | AHB transfer timeout\n");
  531. if (status & A5XX_RBBM_INT_0_MASK_RBBM_ME_MS_TIMEOUT)
  532. dev_err_ratelimited(gpu->dev->dev, "RBBM | ME master split | status=0x%X\n",
  533. gpu_read(gpu, REG_A5XX_RBBM_AHB_ME_SPLIT_STATUS));
  534. if (status & A5XX_RBBM_INT_0_MASK_RBBM_PFP_MS_TIMEOUT)
  535. dev_err_ratelimited(gpu->dev->dev, "RBBM | PFP master split | status=0x%X\n",
  536. gpu_read(gpu, REG_A5XX_RBBM_AHB_PFP_SPLIT_STATUS));
  537. if (status & A5XX_RBBM_INT_0_MASK_RBBM_ETS_MS_TIMEOUT)
  538. dev_err_ratelimited(gpu->dev->dev, "RBBM | ETS master split | status=0x%X\n",
  539. gpu_read(gpu, REG_A5XX_RBBM_AHB_ETS_SPLIT_STATUS));
  540. if (status & A5XX_RBBM_INT_0_MASK_RBBM_ATB_ASYNC_OVERFLOW)
  541. dev_err_ratelimited(gpu->dev->dev, "RBBM | ATB ASYNC overflow\n");
  542. if (status & A5XX_RBBM_INT_0_MASK_RBBM_ATB_BUS_OVERFLOW)
  543. dev_err_ratelimited(gpu->dev->dev, "RBBM | ATB bus overflow\n");
  544. }
  545. static void a5xx_uche_err_irq(struct msm_gpu *gpu)
  546. {
  547. uint64_t addr = (uint64_t) gpu_read(gpu, REG_A5XX_UCHE_TRAP_LOG_HI);
  548. addr |= gpu_read(gpu, REG_A5XX_UCHE_TRAP_LOG_LO);
  549. dev_err_ratelimited(gpu->dev->dev, "UCHE | Out of bounds access | addr=0x%llX\n",
  550. addr);
  551. }
  552. static void a5xx_gpmu_err_irq(struct msm_gpu *gpu)
  553. {
  554. dev_err_ratelimited(gpu->dev->dev, "GPMU | voltage droop\n");
  555. }
  556. #define RBBM_ERROR_MASK \
  557. (A5XX_RBBM_INT_0_MASK_RBBM_AHB_ERROR | \
  558. A5XX_RBBM_INT_0_MASK_RBBM_TRANSFER_TIMEOUT | \
  559. A5XX_RBBM_INT_0_MASK_RBBM_ME_MS_TIMEOUT | \
  560. A5XX_RBBM_INT_0_MASK_RBBM_PFP_MS_TIMEOUT | \
  561. A5XX_RBBM_INT_0_MASK_RBBM_ETS_MS_TIMEOUT | \
  562. A5XX_RBBM_INT_0_MASK_RBBM_ATB_ASYNC_OVERFLOW)
  563. static irqreturn_t a5xx_irq(struct msm_gpu *gpu)
  564. {
  565. u32 status = gpu_read(gpu, REG_A5XX_RBBM_INT_0_STATUS);
  566. gpu_write(gpu, REG_A5XX_RBBM_INT_CLEAR_CMD, status);
  567. if (status & RBBM_ERROR_MASK)
  568. a5xx_rbbm_err_irq(gpu);
  569. if (status & A5XX_RBBM_INT_0_MASK_CP_HW_ERROR)
  570. a5xx_cp_err_irq(gpu);
  571. if (status & A5XX_RBBM_INT_0_MASK_UCHE_OOB_ACCESS)
  572. a5xx_uche_err_irq(gpu);
  573. if (status & A5XX_RBBM_INT_0_MASK_GPMU_VOLTAGE_DROOP)
  574. a5xx_gpmu_err_irq(gpu);
  575. if (status & A5XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS)
  576. msm_gpu_retire(gpu);
  577. return IRQ_HANDLED;
  578. }
  579. static const u32 a5xx_register_offsets[REG_ADRENO_REGISTER_MAX] = {
  580. REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_BASE, REG_A5XX_CP_RB_BASE),
  581. REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_BASE_HI, REG_A5XX_CP_RB_BASE_HI),
  582. REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_RPTR_ADDR, REG_A5XX_CP_RB_RPTR_ADDR),
  583. REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_RPTR_ADDR_HI,
  584. REG_A5XX_CP_RB_RPTR_ADDR_HI),
  585. REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_RPTR, REG_A5XX_CP_RB_RPTR),
  586. REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_WPTR, REG_A5XX_CP_RB_WPTR),
  587. REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_CNTL, REG_A5XX_CP_RB_CNTL),
  588. };
  589. static const u32 a5xx_registers[] = {
  590. 0x0000, 0x0002, 0x0004, 0x0020, 0x0022, 0x0026, 0x0029, 0x002B,
  591. 0x002E, 0x0035, 0x0038, 0x0042, 0x0044, 0x0044, 0x0047, 0x0095,
  592. 0x0097, 0x00BB, 0x03A0, 0x0464, 0x0469, 0x046F, 0x04D2, 0x04D3,
  593. 0x04E0, 0x0533, 0x0540, 0x0555, 0xF400, 0xF400, 0xF800, 0xF807,
  594. 0x0800, 0x081A, 0x081F, 0x0841, 0x0860, 0x0860, 0x0880, 0x08A0,
  595. 0x0B00, 0x0B12, 0x0B15, 0x0B28, 0x0B78, 0x0B7F, 0x0BB0, 0x0BBD,
  596. 0x0BC0, 0x0BC6, 0x0BD0, 0x0C53, 0x0C60, 0x0C61, 0x0C80, 0x0C82,
  597. 0x0C84, 0x0C85, 0x0C90, 0x0C98, 0x0CA0, 0x0CA0, 0x0CB0, 0x0CB2,
  598. 0x2180, 0x2185, 0x2580, 0x2585, 0x0CC1, 0x0CC1, 0x0CC4, 0x0CC7,
  599. 0x0CCC, 0x0CCC, 0x0CD0, 0x0CD8, 0x0CE0, 0x0CE5, 0x0CE8, 0x0CE8,
  600. 0x0CEC, 0x0CF1, 0x0CFB, 0x0D0E, 0x2100, 0x211E, 0x2140, 0x2145,
  601. 0x2500, 0x251E, 0x2540, 0x2545, 0x0D10, 0x0D17, 0x0D20, 0x0D23,
  602. 0x0D30, 0x0D30, 0x20C0, 0x20C0, 0x24C0, 0x24C0, 0x0E40, 0x0E43,
  603. 0x0E4A, 0x0E4A, 0x0E50, 0x0E57, 0x0E60, 0x0E7C, 0x0E80, 0x0E8E,
  604. 0x0E90, 0x0E96, 0x0EA0, 0x0EA8, 0x0EB0, 0x0EB2, 0xE140, 0xE147,
  605. 0xE150, 0xE187, 0xE1A0, 0xE1A9, 0xE1B0, 0xE1B6, 0xE1C0, 0xE1C7,
  606. 0xE1D0, 0xE1D1, 0xE200, 0xE201, 0xE210, 0xE21C, 0xE240, 0xE268,
  607. 0xE000, 0xE006, 0xE010, 0xE09A, 0xE0A0, 0xE0A4, 0xE0AA, 0xE0EB,
  608. 0xE100, 0xE105, 0xE380, 0xE38F, 0xE3B0, 0xE3B0, 0xE400, 0xE405,
  609. 0xE408, 0xE4E9, 0xE4F0, 0xE4F0, 0xE280, 0xE280, 0xE282, 0xE2A3,
  610. 0xE2A5, 0xE2C2, 0xE940, 0xE947, 0xE950, 0xE987, 0xE9A0, 0xE9A9,
  611. 0xE9B0, 0xE9B6, 0xE9C0, 0xE9C7, 0xE9D0, 0xE9D1, 0xEA00, 0xEA01,
  612. 0xEA10, 0xEA1C, 0xEA40, 0xEA68, 0xE800, 0xE806, 0xE810, 0xE89A,
  613. 0xE8A0, 0xE8A4, 0xE8AA, 0xE8EB, 0xE900, 0xE905, 0xEB80, 0xEB8F,
  614. 0xEBB0, 0xEBB0, 0xEC00, 0xEC05, 0xEC08, 0xECE9, 0xECF0, 0xECF0,
  615. 0xEA80, 0xEA80, 0xEA82, 0xEAA3, 0xEAA5, 0xEAC2, 0xA800, 0xA8FF,
  616. 0xAC60, 0xAC60, 0xB000, 0xB97F, 0xB9A0, 0xB9BF,
  617. ~0
  618. };
  619. static void a5xx_dump(struct msm_gpu *gpu)
  620. {
  621. dev_info(gpu->dev->dev, "status: %08x\n",
  622. gpu_read(gpu, REG_A5XX_RBBM_STATUS));
  623. adreno_dump(gpu);
  624. }
  625. static int a5xx_pm_resume(struct msm_gpu *gpu)
  626. {
  627. int ret;
  628. /* Turn on the core power */
  629. ret = msm_gpu_pm_resume(gpu);
  630. if (ret)
  631. return ret;
  632. /* Turn the RBCCU domain first to limit the chances of voltage droop */
  633. gpu_write(gpu, REG_A5XX_GPMU_RBCCU_POWER_CNTL, 0x778000);
  634. /* Wait 3 usecs before polling */
  635. udelay(3);
  636. ret = spin_usecs(gpu, 20, REG_A5XX_GPMU_RBCCU_PWR_CLK_STATUS,
  637. (1 << 20), (1 << 20));
  638. if (ret) {
  639. DRM_ERROR("%s: timeout waiting for RBCCU GDSC enable: %X\n",
  640. gpu->name,
  641. gpu_read(gpu, REG_A5XX_GPMU_RBCCU_PWR_CLK_STATUS));
  642. return ret;
  643. }
  644. /* Turn on the SP domain */
  645. gpu_write(gpu, REG_A5XX_GPMU_SP_POWER_CNTL, 0x778000);
  646. ret = spin_usecs(gpu, 20, REG_A5XX_GPMU_SP_PWR_CLK_STATUS,
  647. (1 << 20), (1 << 20));
  648. if (ret)
  649. DRM_ERROR("%s: timeout waiting for SP GDSC enable\n",
  650. gpu->name);
  651. return ret;
  652. }
  653. static int a5xx_pm_suspend(struct msm_gpu *gpu)
  654. {
  655. /* Clear the VBIF pipe before shutting down */
  656. gpu_write(gpu, REG_A5XX_VBIF_XIN_HALT_CTRL0, 0xF);
  657. spin_until((gpu_read(gpu, REG_A5XX_VBIF_XIN_HALT_CTRL1) & 0xF) == 0xF);
  658. gpu_write(gpu, REG_A5XX_VBIF_XIN_HALT_CTRL0, 0);
  659. /*
  660. * Reset the VBIF before power collapse to avoid issue with FIFO
  661. * entries
  662. */
  663. gpu_write(gpu, REG_A5XX_RBBM_BLOCK_SW_RESET_CMD, 0x003C0000);
  664. gpu_write(gpu, REG_A5XX_RBBM_BLOCK_SW_RESET_CMD, 0x00000000);
  665. return msm_gpu_pm_suspend(gpu);
  666. }
  667. static int a5xx_get_timestamp(struct msm_gpu *gpu, uint64_t *value)
  668. {
  669. *value = gpu_read64(gpu, REG_A5XX_RBBM_PERFCTR_CP_0_LO,
  670. REG_A5XX_RBBM_PERFCTR_CP_0_HI);
  671. return 0;
  672. }
  673. #ifdef CONFIG_DEBUG_FS
  674. static void a5xx_show(struct msm_gpu *gpu, struct seq_file *m)
  675. {
  676. gpu->funcs->pm_resume(gpu);
  677. seq_printf(m, "status: %08x\n",
  678. gpu_read(gpu, REG_A5XX_RBBM_STATUS));
  679. gpu->funcs->pm_suspend(gpu);
  680. adreno_show(gpu, m);
  681. }
  682. #endif
  683. static const struct adreno_gpu_funcs funcs = {
  684. .base = {
  685. .get_param = adreno_get_param,
  686. .hw_init = a5xx_hw_init,
  687. .pm_suspend = a5xx_pm_suspend,
  688. .pm_resume = a5xx_pm_resume,
  689. .recover = a5xx_recover,
  690. .last_fence = adreno_last_fence,
  691. .submit = a5xx_submit,
  692. .flush = adreno_flush,
  693. .idle = a5xx_idle,
  694. .irq = a5xx_irq,
  695. .destroy = a5xx_destroy,
  696. .show = a5xx_show,
  697. },
  698. .get_timestamp = a5xx_get_timestamp,
  699. };
  700. struct msm_gpu *a5xx_gpu_init(struct drm_device *dev)
  701. {
  702. struct msm_drm_private *priv = dev->dev_private;
  703. struct platform_device *pdev = priv->gpu_pdev;
  704. struct a5xx_gpu *a5xx_gpu = NULL;
  705. struct adreno_gpu *adreno_gpu;
  706. struct msm_gpu *gpu;
  707. int ret;
  708. if (!pdev) {
  709. dev_err(dev->dev, "No A5XX device is defined\n");
  710. return ERR_PTR(-ENXIO);
  711. }
  712. a5xx_gpu = kzalloc(sizeof(*a5xx_gpu), GFP_KERNEL);
  713. if (!a5xx_gpu)
  714. return ERR_PTR(-ENOMEM);
  715. adreno_gpu = &a5xx_gpu->base;
  716. gpu = &adreno_gpu->base;
  717. a5xx_gpu->pdev = pdev;
  718. adreno_gpu->registers = a5xx_registers;
  719. adreno_gpu->reg_offsets = a5xx_register_offsets;
  720. a5xx_gpu->lm_leakage = 0x4E001A;
  721. ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs);
  722. if (ret) {
  723. a5xx_destroy(&(a5xx_gpu->base.base));
  724. return ERR_PTR(ret);
  725. }
  726. return gpu;
  727. }