lima_gp.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. // SPDX-License-Identifier: GPL-2.0 OR MIT
  2. /* Copyright 2017-2019 Qiang Yu <[email protected]> */
  3. #include <linux/interrupt.h>
  4. #include <linux/iopoll.h>
  5. #include <linux/device.h>
  6. #include <linux/slab.h>
  7. #include <drm/lima_drm.h>
  8. #include "lima_device.h"
  9. #include "lima_gp.h"
  10. #include "lima_regs.h"
  11. #include "lima_gem.h"
  12. #include "lima_vm.h"
  13. #define gp_write(reg, data) writel(data, ip->iomem + reg)
  14. #define gp_read(reg) readl(ip->iomem + reg)
  15. static irqreturn_t lima_gp_irq_handler(int irq, void *data)
  16. {
  17. struct lima_ip *ip = data;
  18. struct lima_device *dev = ip->dev;
  19. struct lima_sched_pipe *pipe = dev->pipe + lima_pipe_gp;
  20. struct lima_sched_task *task = pipe->current_task;
  21. u32 state = gp_read(LIMA_GP_INT_STAT);
  22. u32 status = gp_read(LIMA_GP_STATUS);
  23. bool done = false;
  24. /* for shared irq case */
  25. if (!state)
  26. return IRQ_NONE;
  27. if (state & LIMA_GP_IRQ_MASK_ERROR) {
  28. if ((state & LIMA_GP_IRQ_MASK_ERROR) ==
  29. LIMA_GP_IRQ_PLBU_OUT_OF_MEM) {
  30. dev_dbg(dev->dev, "gp out of heap irq status=%x\n",
  31. status);
  32. } else {
  33. dev_err(dev->dev, "gp error irq state=%x status=%x\n",
  34. state, status);
  35. if (task)
  36. task->recoverable = false;
  37. }
  38. /* mask all interrupts before hard reset */
  39. gp_write(LIMA_GP_INT_MASK, 0);
  40. pipe->error = true;
  41. done = true;
  42. } else {
  43. bool valid = state & (LIMA_GP_IRQ_VS_END_CMD_LST |
  44. LIMA_GP_IRQ_PLBU_END_CMD_LST);
  45. bool active = status & (LIMA_GP_STATUS_VS_ACTIVE |
  46. LIMA_GP_STATUS_PLBU_ACTIVE);
  47. done = valid && !active;
  48. pipe->error = false;
  49. }
  50. gp_write(LIMA_GP_INT_CLEAR, state);
  51. if (done)
  52. lima_sched_pipe_task_done(pipe);
  53. return IRQ_HANDLED;
  54. }
  55. static void lima_gp_soft_reset_async(struct lima_ip *ip)
  56. {
  57. if (ip->data.async_reset)
  58. return;
  59. gp_write(LIMA_GP_INT_MASK, 0);
  60. gp_write(LIMA_GP_INT_CLEAR, LIMA_GP_IRQ_RESET_COMPLETED);
  61. gp_write(LIMA_GP_CMD, LIMA_GP_CMD_SOFT_RESET);
  62. ip->data.async_reset = true;
  63. }
  64. static int lima_gp_soft_reset_async_wait(struct lima_ip *ip)
  65. {
  66. struct lima_device *dev = ip->dev;
  67. int err;
  68. u32 v;
  69. if (!ip->data.async_reset)
  70. return 0;
  71. err = readl_poll_timeout(ip->iomem + LIMA_GP_INT_RAWSTAT, v,
  72. v & LIMA_GP_IRQ_RESET_COMPLETED,
  73. 0, 100);
  74. if (err) {
  75. dev_err(dev->dev, "gp soft reset time out\n");
  76. return err;
  77. }
  78. gp_write(LIMA_GP_INT_CLEAR, LIMA_GP_IRQ_MASK_ALL);
  79. gp_write(LIMA_GP_INT_MASK, LIMA_GP_IRQ_MASK_USED);
  80. ip->data.async_reset = false;
  81. return 0;
  82. }
  83. static int lima_gp_task_validate(struct lima_sched_pipe *pipe,
  84. struct lima_sched_task *task)
  85. {
  86. struct drm_lima_gp_frame *frame = task->frame;
  87. u32 *f = frame->frame;
  88. (void)pipe;
  89. if (f[LIMA_GP_VSCL_START_ADDR >> 2] >
  90. f[LIMA_GP_VSCL_END_ADDR >> 2] ||
  91. f[LIMA_GP_PLBUCL_START_ADDR >> 2] >
  92. f[LIMA_GP_PLBUCL_END_ADDR >> 2] ||
  93. f[LIMA_GP_PLBU_ALLOC_START_ADDR >> 2] >
  94. f[LIMA_GP_PLBU_ALLOC_END_ADDR >> 2])
  95. return -EINVAL;
  96. if (f[LIMA_GP_VSCL_START_ADDR >> 2] ==
  97. f[LIMA_GP_VSCL_END_ADDR >> 2] &&
  98. f[LIMA_GP_PLBUCL_START_ADDR >> 2] ==
  99. f[LIMA_GP_PLBUCL_END_ADDR >> 2])
  100. return -EINVAL;
  101. return 0;
  102. }
  103. static void lima_gp_task_run(struct lima_sched_pipe *pipe,
  104. struct lima_sched_task *task)
  105. {
  106. struct lima_ip *ip = pipe->processor[0];
  107. struct drm_lima_gp_frame *frame = task->frame;
  108. u32 *f = frame->frame;
  109. u32 cmd = 0;
  110. int i;
  111. /* update real heap buffer size for GP */
  112. for (i = 0; i < task->num_bos; i++) {
  113. struct lima_bo *bo = task->bos[i];
  114. if (bo->heap_size &&
  115. lima_vm_get_va(task->vm, bo) ==
  116. f[LIMA_GP_PLBU_ALLOC_START_ADDR >> 2]) {
  117. f[LIMA_GP_PLBU_ALLOC_END_ADDR >> 2] =
  118. f[LIMA_GP_PLBU_ALLOC_START_ADDR >> 2] +
  119. bo->heap_size;
  120. task->recoverable = true;
  121. task->heap = bo;
  122. break;
  123. }
  124. }
  125. if (f[LIMA_GP_VSCL_START_ADDR >> 2] !=
  126. f[LIMA_GP_VSCL_END_ADDR >> 2])
  127. cmd |= LIMA_GP_CMD_START_VS;
  128. if (f[LIMA_GP_PLBUCL_START_ADDR >> 2] !=
  129. f[LIMA_GP_PLBUCL_END_ADDR >> 2])
  130. cmd |= LIMA_GP_CMD_START_PLBU;
  131. /* before any hw ops, wait last success task async soft reset */
  132. lima_gp_soft_reset_async_wait(ip);
  133. for (i = 0; i < LIMA_GP_FRAME_REG_NUM; i++)
  134. writel(f[i], ip->iomem + LIMA_GP_VSCL_START_ADDR + i * 4);
  135. gp_write(LIMA_GP_CMD, LIMA_GP_CMD_UPDATE_PLBU_ALLOC);
  136. gp_write(LIMA_GP_CMD, cmd);
  137. }
  138. static int lima_gp_hard_reset_poll(struct lima_ip *ip)
  139. {
  140. gp_write(LIMA_GP_PERF_CNT_0_LIMIT, 0xC01A0000);
  141. return gp_read(LIMA_GP_PERF_CNT_0_LIMIT) == 0xC01A0000;
  142. }
  143. static int lima_gp_hard_reset(struct lima_ip *ip)
  144. {
  145. struct lima_device *dev = ip->dev;
  146. int ret;
  147. gp_write(LIMA_GP_PERF_CNT_0_LIMIT, 0xC0FFE000);
  148. gp_write(LIMA_GP_INT_MASK, 0);
  149. gp_write(LIMA_GP_CMD, LIMA_GP_CMD_RESET);
  150. ret = lima_poll_timeout(ip, lima_gp_hard_reset_poll, 10, 100);
  151. if (ret) {
  152. dev_err(dev->dev, "gp hard reset timeout\n");
  153. return ret;
  154. }
  155. gp_write(LIMA_GP_PERF_CNT_0_LIMIT, 0);
  156. gp_write(LIMA_GP_INT_CLEAR, LIMA_GP_IRQ_MASK_ALL);
  157. gp_write(LIMA_GP_INT_MASK, LIMA_GP_IRQ_MASK_USED);
  158. return 0;
  159. }
  160. static void lima_gp_task_fini(struct lima_sched_pipe *pipe)
  161. {
  162. lima_gp_soft_reset_async(pipe->processor[0]);
  163. }
  164. static void lima_gp_task_error(struct lima_sched_pipe *pipe)
  165. {
  166. struct lima_ip *ip = pipe->processor[0];
  167. dev_err(ip->dev->dev, "gp task error int_state=%x status=%x\n",
  168. gp_read(LIMA_GP_INT_STAT), gp_read(LIMA_GP_STATUS));
  169. lima_gp_hard_reset(ip);
  170. }
  171. static void lima_gp_task_mmu_error(struct lima_sched_pipe *pipe)
  172. {
  173. lima_sched_pipe_task_done(pipe);
  174. }
  175. static int lima_gp_task_recover(struct lima_sched_pipe *pipe)
  176. {
  177. struct lima_ip *ip = pipe->processor[0];
  178. struct lima_sched_task *task = pipe->current_task;
  179. struct drm_lima_gp_frame *frame = task->frame;
  180. u32 *f = frame->frame;
  181. size_t fail_size =
  182. f[LIMA_GP_PLBU_ALLOC_END_ADDR >> 2] -
  183. f[LIMA_GP_PLBU_ALLOC_START_ADDR >> 2];
  184. if (fail_size == task->heap->heap_size) {
  185. int ret;
  186. ret = lima_heap_alloc(task->heap, task->vm);
  187. if (ret < 0)
  188. return ret;
  189. }
  190. gp_write(LIMA_GP_INT_MASK, LIMA_GP_IRQ_MASK_USED);
  191. /* Resume from where we stopped, i.e. new start is old end */
  192. gp_write(LIMA_GP_PLBU_ALLOC_START_ADDR,
  193. f[LIMA_GP_PLBU_ALLOC_END_ADDR >> 2]);
  194. f[LIMA_GP_PLBU_ALLOC_END_ADDR >> 2] =
  195. f[LIMA_GP_PLBU_ALLOC_START_ADDR >> 2] + task->heap->heap_size;
  196. gp_write(LIMA_GP_PLBU_ALLOC_END_ADDR,
  197. f[LIMA_GP_PLBU_ALLOC_END_ADDR >> 2]);
  198. gp_write(LIMA_GP_CMD, LIMA_GP_CMD_UPDATE_PLBU_ALLOC);
  199. return 0;
  200. }
  201. static void lima_gp_print_version(struct lima_ip *ip)
  202. {
  203. u32 version, major, minor;
  204. char *name;
  205. version = gp_read(LIMA_GP_VERSION);
  206. major = (version >> 8) & 0xFF;
  207. minor = version & 0xFF;
  208. switch (version >> 16) {
  209. case 0xA07:
  210. name = "mali200";
  211. break;
  212. case 0xC07:
  213. name = "mali300";
  214. break;
  215. case 0xB07:
  216. name = "mali400";
  217. break;
  218. case 0xD07:
  219. name = "mali450";
  220. break;
  221. default:
  222. name = "unknown";
  223. break;
  224. }
  225. dev_info(ip->dev->dev, "%s - %s version major %d minor %d\n",
  226. lima_ip_name(ip), name, major, minor);
  227. }
  228. static struct kmem_cache *lima_gp_task_slab;
  229. static int lima_gp_task_slab_refcnt;
  230. static int lima_gp_hw_init(struct lima_ip *ip)
  231. {
  232. ip->data.async_reset = false;
  233. lima_gp_soft_reset_async(ip);
  234. return lima_gp_soft_reset_async_wait(ip);
  235. }
  236. int lima_gp_resume(struct lima_ip *ip)
  237. {
  238. return lima_gp_hw_init(ip);
  239. }
  240. void lima_gp_suspend(struct lima_ip *ip)
  241. {
  242. }
  243. int lima_gp_init(struct lima_ip *ip)
  244. {
  245. struct lima_device *dev = ip->dev;
  246. int err;
  247. lima_gp_print_version(ip);
  248. err = lima_gp_hw_init(ip);
  249. if (err)
  250. return err;
  251. err = devm_request_irq(dev->dev, ip->irq, lima_gp_irq_handler,
  252. IRQF_SHARED, lima_ip_name(ip), ip);
  253. if (err) {
  254. dev_err(dev->dev, "gp %s fail to request irq\n",
  255. lima_ip_name(ip));
  256. return err;
  257. }
  258. dev->gp_version = gp_read(LIMA_GP_VERSION);
  259. return 0;
  260. }
  261. void lima_gp_fini(struct lima_ip *ip)
  262. {
  263. }
  264. int lima_gp_pipe_init(struct lima_device *dev)
  265. {
  266. int frame_size = sizeof(struct drm_lima_gp_frame);
  267. struct lima_sched_pipe *pipe = dev->pipe + lima_pipe_gp;
  268. if (!lima_gp_task_slab) {
  269. lima_gp_task_slab = kmem_cache_create_usercopy(
  270. "lima_gp_task", sizeof(struct lima_sched_task) + frame_size,
  271. 0, SLAB_HWCACHE_ALIGN, sizeof(struct lima_sched_task),
  272. frame_size, NULL);
  273. if (!lima_gp_task_slab)
  274. return -ENOMEM;
  275. }
  276. lima_gp_task_slab_refcnt++;
  277. pipe->frame_size = frame_size;
  278. pipe->task_slab = lima_gp_task_slab;
  279. pipe->task_validate = lima_gp_task_validate;
  280. pipe->task_run = lima_gp_task_run;
  281. pipe->task_fini = lima_gp_task_fini;
  282. pipe->task_error = lima_gp_task_error;
  283. pipe->task_mmu_error = lima_gp_task_mmu_error;
  284. pipe->task_recover = lima_gp_task_recover;
  285. return 0;
  286. }
  287. void lima_gp_pipe_fini(struct lima_device *dev)
  288. {
  289. if (!--lima_gp_task_slab_refcnt) {
  290. kmem_cache_destroy(lima_gp_task_slab);
  291. lima_gp_task_slab = NULL;
  292. }
  293. }