lima_gp.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. // SPDX-License-Identifier: GPL-2.0 OR MIT
  2. /* Copyright 2017-2019 Qiang Yu <yuq825@gmail.com> */
  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, "%s out of heap irq status=%x\n",
  31. lima_ip_name(ip), status);
  32. } else {
  33. dev_err(dev->dev, "%s error irq state=%x status=%x\n",
  34. lima_ip_name(ip), 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, "%s soft reset time out\n",
  76. lima_ip_name(ip));
  77. return err;
  78. }
  79. gp_write(LIMA_GP_INT_CLEAR, LIMA_GP_IRQ_MASK_ALL);
  80. gp_write(LIMA_GP_INT_MASK, LIMA_GP_IRQ_MASK_USED);
  81. ip->data.async_reset = false;
  82. return 0;
  83. }
  84. static int lima_gp_task_validate(struct lima_sched_pipe *pipe,
  85. struct lima_sched_task *task)
  86. {
  87. struct drm_lima_gp_frame *frame = task->frame;
  88. u32 *f = frame->frame;
  89. (void)pipe;
  90. if (f[LIMA_GP_VSCL_START_ADDR >> 2] >
  91. f[LIMA_GP_VSCL_END_ADDR >> 2] ||
  92. f[LIMA_GP_PLBUCL_START_ADDR >> 2] >
  93. f[LIMA_GP_PLBUCL_END_ADDR >> 2] ||
  94. f[LIMA_GP_PLBU_ALLOC_START_ADDR >> 2] >
  95. f[LIMA_GP_PLBU_ALLOC_END_ADDR >> 2])
  96. return -EINVAL;
  97. if (f[LIMA_GP_VSCL_START_ADDR >> 2] ==
  98. f[LIMA_GP_VSCL_END_ADDR >> 2] &&
  99. f[LIMA_GP_PLBUCL_START_ADDR >> 2] ==
  100. f[LIMA_GP_PLBUCL_END_ADDR >> 2])
  101. return -EINVAL;
  102. return 0;
  103. }
  104. static void lima_gp_task_run(struct lima_sched_pipe *pipe,
  105. struct lima_sched_task *task)
  106. {
  107. struct lima_ip *ip = pipe->processor[0];
  108. struct drm_lima_gp_frame *frame = task->frame;
  109. u32 *f = frame->frame;
  110. u32 cmd = 0;
  111. int i;
  112. /* update real heap buffer size for GP */
  113. for (i = 0; i < task->num_bos; i++) {
  114. struct lima_bo *bo = task->bos[i];
  115. if (bo->heap_size &&
  116. lima_vm_get_va(task->vm, bo) ==
  117. f[LIMA_GP_PLBU_ALLOC_START_ADDR >> 2]) {
  118. f[LIMA_GP_PLBU_ALLOC_END_ADDR >> 2] =
  119. f[LIMA_GP_PLBU_ALLOC_START_ADDR >> 2] +
  120. bo->heap_size;
  121. task->recoverable = true;
  122. task->heap = bo;
  123. break;
  124. }
  125. }
  126. if (f[LIMA_GP_VSCL_START_ADDR >> 2] !=
  127. f[LIMA_GP_VSCL_END_ADDR >> 2])
  128. cmd |= LIMA_GP_CMD_START_VS;
  129. if (f[LIMA_GP_PLBUCL_START_ADDR >> 2] !=
  130. f[LIMA_GP_PLBUCL_END_ADDR >> 2])
  131. cmd |= LIMA_GP_CMD_START_PLBU;
  132. /* before any hw ops, wait last success task async soft reset */
  133. lima_gp_soft_reset_async_wait(ip);
  134. for (i = 0; i < LIMA_GP_FRAME_REG_NUM; i++)
  135. writel(f[i], ip->iomem + LIMA_GP_VSCL_START_ADDR + i * 4);
  136. gp_write(LIMA_GP_CMD, LIMA_GP_CMD_UPDATE_PLBU_ALLOC);
  137. gp_write(LIMA_GP_CMD, cmd);
  138. }
  139. static int lima_gp_bus_stop_poll(struct lima_ip *ip)
  140. {
  141. return !!(gp_read(LIMA_GP_STATUS) & LIMA_GP_STATUS_BUS_STOPPED);
  142. }
  143. static int lima_gp_hard_reset_poll(struct lima_ip *ip)
  144. {
  145. gp_write(LIMA_GP_PERF_CNT_0_LIMIT, 0xC01A0000);
  146. return gp_read(LIMA_GP_PERF_CNT_0_LIMIT) == 0xC01A0000;
  147. }
  148. static int lima_gp_hard_reset(struct lima_ip *ip)
  149. {
  150. struct lima_device *dev = ip->dev;
  151. int ret;
  152. gp_write(LIMA_GP_PERF_CNT_0_LIMIT, 0xC0FFE000);
  153. gp_write(LIMA_GP_INT_MASK, 0);
  154. gp_write(LIMA_GP_CMD, LIMA_GP_CMD_STOP_BUS);
  155. ret = lima_poll_timeout(ip, lima_gp_bus_stop_poll, 10, 100);
  156. if (ret) {
  157. dev_err(dev->dev, "%s bus stop timeout\n", lima_ip_name(ip));
  158. return ret;
  159. }
  160. gp_write(LIMA_GP_CMD, LIMA_GP_CMD_RESET);
  161. ret = lima_poll_timeout(ip, lima_gp_hard_reset_poll, 10, 100);
  162. if (ret) {
  163. dev_err(dev->dev, "%s hard reset timeout\n", lima_ip_name(ip));
  164. return ret;
  165. }
  166. gp_write(LIMA_GP_PERF_CNT_0_LIMIT, 0);
  167. gp_write(LIMA_GP_INT_CLEAR, LIMA_GP_IRQ_MASK_ALL);
  168. gp_write(LIMA_GP_INT_MASK, LIMA_GP_IRQ_MASK_USED);
  169. /*
  170. * if there was an async soft reset queued,
  171. * don't wait for it in the next job
  172. */
  173. ip->data.async_reset = false;
  174. return 0;
  175. }
  176. static void lima_gp_task_fini(struct lima_sched_pipe *pipe)
  177. {
  178. lima_gp_soft_reset_async(pipe->processor[0]);
  179. }
  180. static void lima_gp_task_error(struct lima_sched_pipe *pipe)
  181. {
  182. struct lima_ip *ip = pipe->processor[0];
  183. dev_err(ip->dev->dev, "%s task error int_state=%x status=%x\n",
  184. lima_ip_name(ip), gp_read(LIMA_GP_INT_STAT),
  185. gp_read(LIMA_GP_STATUS));
  186. lima_gp_hard_reset(ip);
  187. }
  188. static void lima_gp_task_mmu_error(struct lima_sched_pipe *pipe)
  189. {
  190. lima_sched_pipe_task_done(pipe);
  191. }
  192. static void lima_gp_task_mask_irq(struct lima_sched_pipe *pipe)
  193. {
  194. struct lima_ip *ip = pipe->processor[0];
  195. gp_write(LIMA_GP_INT_MASK, 0);
  196. }
  197. static int lima_gp_task_recover(struct lima_sched_pipe *pipe)
  198. {
  199. struct lima_ip *ip = pipe->processor[0];
  200. struct lima_sched_task *task = pipe->current_task;
  201. struct drm_lima_gp_frame *frame = task->frame;
  202. u32 *f = frame->frame;
  203. size_t fail_size =
  204. f[LIMA_GP_PLBU_ALLOC_END_ADDR >> 2] -
  205. f[LIMA_GP_PLBU_ALLOC_START_ADDR >> 2];
  206. if (fail_size == task->heap->heap_size) {
  207. int ret;
  208. ret = lima_heap_alloc(task->heap, task->vm);
  209. if (ret < 0)
  210. return ret;
  211. }
  212. gp_write(LIMA_GP_INT_MASK, LIMA_GP_IRQ_MASK_USED);
  213. /* Resume from where we stopped, i.e. new start is old end */
  214. gp_write(LIMA_GP_PLBU_ALLOC_START_ADDR,
  215. f[LIMA_GP_PLBU_ALLOC_END_ADDR >> 2]);
  216. f[LIMA_GP_PLBU_ALLOC_END_ADDR >> 2] =
  217. f[LIMA_GP_PLBU_ALLOC_START_ADDR >> 2] + task->heap->heap_size;
  218. gp_write(LIMA_GP_PLBU_ALLOC_END_ADDR,
  219. f[LIMA_GP_PLBU_ALLOC_END_ADDR >> 2]);
  220. gp_write(LIMA_GP_CMD, LIMA_GP_CMD_UPDATE_PLBU_ALLOC);
  221. return 0;
  222. }
  223. static void lima_gp_print_version(struct lima_ip *ip)
  224. {
  225. u32 version, major, minor;
  226. char *name;
  227. version = gp_read(LIMA_GP_VERSION);
  228. major = (version >> 8) & 0xFF;
  229. minor = version & 0xFF;
  230. switch (version >> 16) {
  231. case 0xA07:
  232. name = "mali200";
  233. break;
  234. case 0xC07:
  235. name = "mali300";
  236. break;
  237. case 0xB07:
  238. name = "mali400";
  239. break;
  240. case 0xD07:
  241. name = "mali450";
  242. break;
  243. default:
  244. name = "unknown";
  245. break;
  246. }
  247. dev_info(ip->dev->dev, "%s - %s version major %d minor %d\n",
  248. lima_ip_name(ip), name, major, minor);
  249. }
  250. static struct kmem_cache *lima_gp_task_slab;
  251. static int lima_gp_task_slab_refcnt;
  252. static int lima_gp_hw_init(struct lima_ip *ip)
  253. {
  254. ip->data.async_reset = false;
  255. lima_gp_soft_reset_async(ip);
  256. return lima_gp_soft_reset_async_wait(ip);
  257. }
  258. int lima_gp_resume(struct lima_ip *ip)
  259. {
  260. return lima_gp_hw_init(ip);
  261. }
  262. void lima_gp_suspend(struct lima_ip *ip)
  263. {
  264. }
  265. int lima_gp_init(struct lima_ip *ip)
  266. {
  267. struct lima_device *dev = ip->dev;
  268. int err;
  269. lima_gp_print_version(ip);
  270. err = lima_gp_hw_init(ip);
  271. if (err)
  272. return err;
  273. err = devm_request_irq(dev->dev, ip->irq, lima_gp_irq_handler,
  274. IRQF_SHARED, lima_ip_name(ip), ip);
  275. if (err) {
  276. dev_err(dev->dev, "%s fail to request irq\n",
  277. lima_ip_name(ip));
  278. return err;
  279. }
  280. dev->gp_version = gp_read(LIMA_GP_VERSION);
  281. return 0;
  282. }
  283. void lima_gp_fini(struct lima_ip *ip)
  284. {
  285. struct lima_device *dev = ip->dev;
  286. devm_free_irq(dev->dev, ip->irq, ip);
  287. }
  288. int lima_gp_pipe_init(struct lima_device *dev)
  289. {
  290. int frame_size = sizeof(struct drm_lima_gp_frame);
  291. struct lima_sched_pipe *pipe = dev->pipe + lima_pipe_gp;
  292. if (!lima_gp_task_slab) {
  293. lima_gp_task_slab = kmem_cache_create_usercopy(
  294. "lima_gp_task", sizeof(struct lima_sched_task) + frame_size,
  295. 0, SLAB_HWCACHE_ALIGN, sizeof(struct lima_sched_task),
  296. frame_size, NULL);
  297. if (!lima_gp_task_slab)
  298. return -ENOMEM;
  299. }
  300. lima_gp_task_slab_refcnt++;
  301. pipe->frame_size = frame_size;
  302. pipe->task_slab = lima_gp_task_slab;
  303. pipe->task_validate = lima_gp_task_validate;
  304. pipe->task_run = lima_gp_task_run;
  305. pipe->task_fini = lima_gp_task_fini;
  306. pipe->task_error = lima_gp_task_error;
  307. pipe->task_mmu_error = lima_gp_task_mmu_error;
  308. pipe->task_recover = lima_gp_task_recover;
  309. pipe->task_mask_irq = lima_gp_task_mask_irq;
  310. return 0;
  311. }
  312. void lima_gp_pipe_fini(struct lima_device *dev)
  313. {
  314. if (!--lima_gp_task_slab_refcnt) {
  315. kmem_cache_destroy(lima_gp_task_slab);
  316. lima_gp_task_slab = NULL;
  317. }
  318. }