vc4_v3d.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. /*
  2. * Copyright (c) 2014 The Linux Foundation. All rights reserved.
  3. * Copyright (C) 2013 Red Hat
  4. * Author: Rob Clark <robdclark@gmail.com>
  5. *
  6. * This program is free software; you can redistribute it and/or modify it
  7. * under the terms of the GNU General Public License version 2 as published by
  8. * the Free Software Foundation.
  9. *
  10. * This program is distributed in the hope that it will be useful, but WITHOUT
  11. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  13. * more details.
  14. *
  15. * You should have received a copy of the GNU General Public License along with
  16. * this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include "linux/component.h"
  19. #include "vc4_drv.h"
  20. #include "vc4_regs.h"
  21. #ifdef CONFIG_DEBUG_FS
  22. #define REGDEF(reg) { reg, #reg }
  23. static const struct {
  24. uint32_t reg;
  25. const char *name;
  26. } vc4_reg_defs[] = {
  27. REGDEF(V3D_IDENT0),
  28. REGDEF(V3D_IDENT1),
  29. REGDEF(V3D_IDENT2),
  30. REGDEF(V3D_SCRATCH),
  31. REGDEF(V3D_L2CACTL),
  32. REGDEF(V3D_SLCACTL),
  33. REGDEF(V3D_INTCTL),
  34. REGDEF(V3D_INTENA),
  35. REGDEF(V3D_INTDIS),
  36. REGDEF(V3D_CT0CS),
  37. REGDEF(V3D_CT1CS),
  38. REGDEF(V3D_CT0EA),
  39. REGDEF(V3D_CT1EA),
  40. REGDEF(V3D_CT0CA),
  41. REGDEF(V3D_CT1CA),
  42. REGDEF(V3D_CT00RA0),
  43. REGDEF(V3D_CT01RA0),
  44. REGDEF(V3D_CT0LC),
  45. REGDEF(V3D_CT1LC),
  46. REGDEF(V3D_CT0PC),
  47. REGDEF(V3D_CT1PC),
  48. REGDEF(V3D_PCS),
  49. REGDEF(V3D_BFC),
  50. REGDEF(V3D_RFC),
  51. REGDEF(V3D_BPCA),
  52. REGDEF(V3D_BPCS),
  53. REGDEF(V3D_BPOA),
  54. REGDEF(V3D_BPOS),
  55. REGDEF(V3D_BXCF),
  56. REGDEF(V3D_SQRSV0),
  57. REGDEF(V3D_SQRSV1),
  58. REGDEF(V3D_SQCNTL),
  59. REGDEF(V3D_SRQPC),
  60. REGDEF(V3D_SRQUA),
  61. REGDEF(V3D_SRQUL),
  62. REGDEF(V3D_SRQCS),
  63. REGDEF(V3D_VPACNTL),
  64. REGDEF(V3D_VPMBASE),
  65. REGDEF(V3D_PCTRC),
  66. REGDEF(V3D_PCTRE),
  67. REGDEF(V3D_PCTR0),
  68. REGDEF(V3D_PCTRS0),
  69. REGDEF(V3D_PCTR1),
  70. REGDEF(V3D_PCTRS1),
  71. REGDEF(V3D_PCTR2),
  72. REGDEF(V3D_PCTRS2),
  73. REGDEF(V3D_PCTR3),
  74. REGDEF(V3D_PCTRS3),
  75. REGDEF(V3D_PCTR4),
  76. REGDEF(V3D_PCTRS4),
  77. REGDEF(V3D_PCTR5),
  78. REGDEF(V3D_PCTRS5),
  79. REGDEF(V3D_PCTR6),
  80. REGDEF(V3D_PCTRS6),
  81. REGDEF(V3D_PCTR7),
  82. REGDEF(V3D_PCTRS7),
  83. REGDEF(V3D_PCTR8),
  84. REGDEF(V3D_PCTRS8),
  85. REGDEF(V3D_PCTR9),
  86. REGDEF(V3D_PCTRS9),
  87. REGDEF(V3D_PCTR10),
  88. REGDEF(V3D_PCTRS10),
  89. REGDEF(V3D_PCTR11),
  90. REGDEF(V3D_PCTRS11),
  91. REGDEF(V3D_PCTR12),
  92. REGDEF(V3D_PCTRS12),
  93. REGDEF(V3D_PCTR13),
  94. REGDEF(V3D_PCTRS13),
  95. REGDEF(V3D_PCTR14),
  96. REGDEF(V3D_PCTRS14),
  97. REGDEF(V3D_PCTR15),
  98. REGDEF(V3D_PCTRS15),
  99. REGDEF(V3D_DBGE),
  100. REGDEF(V3D_FDBGO),
  101. REGDEF(V3D_FDBGB),
  102. REGDEF(V3D_FDBGR),
  103. REGDEF(V3D_FDBGS),
  104. REGDEF(V3D_ERRSTAT),
  105. };
  106. int vc4_v3d_debugfs_regs(struct seq_file *m, void *unused)
  107. {
  108. struct drm_info_node *node = (struct drm_info_node *)m->private;
  109. struct drm_device *dev = node->minor->dev;
  110. struct vc4_dev *vc4 = to_vc4_dev(dev);
  111. int i;
  112. for (i = 0; i < ARRAY_SIZE(vc4_reg_defs); i++) {
  113. seq_printf(m, "%s (0x%04x): 0x%08x\n",
  114. vc4_reg_defs[i].name, vc4_reg_defs[i].reg,
  115. V3D_READ(vc4_reg_defs[i].reg));
  116. }
  117. return 0;
  118. }
  119. int vc4_v3d_debugfs_ident(struct seq_file *m, void *unused)
  120. {
  121. struct drm_info_node *node = (struct drm_info_node *)m->private;
  122. struct drm_device *dev = node->minor->dev;
  123. struct vc4_dev *vc4 = to_vc4_dev(dev);
  124. uint32_t ident1 = V3D_READ(V3D_IDENT1);
  125. uint32_t nslc = VC4_GET_FIELD(ident1, V3D_IDENT1_NSLC);
  126. uint32_t tups = VC4_GET_FIELD(ident1, V3D_IDENT1_TUPS);
  127. uint32_t qups = VC4_GET_FIELD(ident1, V3D_IDENT1_QUPS);
  128. seq_printf(m, "Revision: %d\n",
  129. VC4_GET_FIELD(ident1, V3D_IDENT1_REV));
  130. seq_printf(m, "Slices: %d\n", nslc);
  131. seq_printf(m, "TMUs: %d\n", nslc * tups);
  132. seq_printf(m, "QPUs: %d\n", nslc * qups);
  133. seq_printf(m, "Semaphores: %d\n",
  134. VC4_GET_FIELD(ident1, V3D_IDENT1_NSEM));
  135. return 0;
  136. }
  137. #endif /* CONFIG_DEBUG_FS */
  138. int
  139. vc4_v3d_set_power(struct vc4_dev *vc4, bool on)
  140. {
  141. /* XXX: This interface is needed for GPU reset, and the way to
  142. * do it is to turn our power domain off and back on. We
  143. * can't just reset from within the driver, because the reset
  144. * bits are in the power domain's register area, and get set
  145. * during the poweron process.
  146. */
  147. return 0;
  148. }
  149. static void vc4_v3d_init_hw(struct drm_device *dev)
  150. {
  151. struct vc4_dev *vc4 = to_vc4_dev(dev);
  152. /* Take all the memory that would have been reserved for user
  153. * QPU programs, since we don't have an interface for running
  154. * them, anyway.
  155. */
  156. V3D_WRITE(V3D_VPMBASE, 0);
  157. }
  158. static int vc4_v3d_bind(struct device *dev, struct device *master, void *data)
  159. {
  160. struct platform_device *pdev = to_platform_device(dev);
  161. struct drm_device *drm = dev_get_drvdata(master);
  162. struct vc4_dev *vc4 = to_vc4_dev(drm);
  163. struct vc4_v3d *v3d = NULL;
  164. int ret;
  165. v3d = devm_kzalloc(&pdev->dev, sizeof(*v3d), GFP_KERNEL);
  166. if (!v3d)
  167. return -ENOMEM;
  168. v3d->pdev = pdev;
  169. v3d->regs = vc4_ioremap_regs(pdev, 0);
  170. if (IS_ERR(v3d->regs))
  171. return PTR_ERR(v3d->regs);
  172. vc4->v3d = v3d;
  173. if (V3D_READ(V3D_IDENT0) != V3D_EXPECTED_IDENT0) {
  174. DRM_ERROR("V3D_IDENT0 read 0x%08x instead of 0x%08x\n",
  175. V3D_READ(V3D_IDENT0), V3D_EXPECTED_IDENT0);
  176. return -EINVAL;
  177. }
  178. /* Reset the binner overflow address/size at setup, to be sure
  179. * we don't reuse an old one.
  180. */
  181. V3D_WRITE(V3D_BPOA, 0);
  182. V3D_WRITE(V3D_BPOS, 0);
  183. vc4_v3d_init_hw(drm);
  184. ret = drm_irq_install(drm, platform_get_irq(pdev, 0));
  185. if (ret) {
  186. DRM_ERROR("Failed to install IRQ handler\n");
  187. return ret;
  188. }
  189. return 0;
  190. }
  191. static void vc4_v3d_unbind(struct device *dev, struct device *master,
  192. void *data)
  193. {
  194. struct drm_device *drm = dev_get_drvdata(master);
  195. struct vc4_dev *vc4 = to_vc4_dev(drm);
  196. drm_irq_uninstall(drm);
  197. /* Disable the binner's overflow memory address, so the next
  198. * driver probe (if any) doesn't try to reuse our old
  199. * allocation.
  200. */
  201. V3D_WRITE(V3D_BPOA, 0);
  202. V3D_WRITE(V3D_BPOS, 0);
  203. vc4->v3d = NULL;
  204. }
  205. static const struct component_ops vc4_v3d_ops = {
  206. .bind = vc4_v3d_bind,
  207. .unbind = vc4_v3d_unbind,
  208. };
  209. static int vc4_v3d_dev_probe(struct platform_device *pdev)
  210. {
  211. return component_add(&pdev->dev, &vc4_v3d_ops);
  212. }
  213. static int vc4_v3d_dev_remove(struct platform_device *pdev)
  214. {
  215. component_del(&pdev->dev, &vc4_v3d_ops);
  216. return 0;
  217. }
  218. static const struct of_device_id vc4_v3d_dt_match[] = {
  219. { .compatible = "brcm,vc4-v3d" },
  220. {}
  221. };
  222. struct platform_driver vc4_v3d_driver = {
  223. .probe = vc4_v3d_dev_probe,
  224. .remove = vc4_v3d_dev_remove,
  225. .driver = {
  226. .name = "vc4_v3d",
  227. .of_match_table = vc4_v3d_dt_match,
  228. },
  229. };