blob: a88078d7c9d141ec4a50ddce558a213068fcd169 [file] [log] [blame]
Eric Anholtd3f51682015-03-02 13:01:12 -08001/*
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
19#include "linux/component.h"
Eric Anholt001bdb52016-02-05 17:41:49 -080020#include "linux/pm_runtime.h"
Eric Anholtd3f51682015-03-02 13:01:12 -080021#include "vc4_drv.h"
22#include "vc4_regs.h"
23
24#ifdef CONFIG_DEBUG_FS
25#define REGDEF(reg) { reg, #reg }
26static const struct {
27 uint32_t reg;
28 const char *name;
29} vc4_reg_defs[] = {
30 REGDEF(V3D_IDENT0),
31 REGDEF(V3D_IDENT1),
32 REGDEF(V3D_IDENT2),
33 REGDEF(V3D_SCRATCH),
34 REGDEF(V3D_L2CACTL),
35 REGDEF(V3D_SLCACTL),
36 REGDEF(V3D_INTCTL),
37 REGDEF(V3D_INTENA),
38 REGDEF(V3D_INTDIS),
39 REGDEF(V3D_CT0CS),
40 REGDEF(V3D_CT1CS),
41 REGDEF(V3D_CT0EA),
42 REGDEF(V3D_CT1EA),
43 REGDEF(V3D_CT0CA),
44 REGDEF(V3D_CT1CA),
45 REGDEF(V3D_CT00RA0),
46 REGDEF(V3D_CT01RA0),
47 REGDEF(V3D_CT0LC),
48 REGDEF(V3D_CT1LC),
49 REGDEF(V3D_CT0PC),
50 REGDEF(V3D_CT1PC),
51 REGDEF(V3D_PCS),
52 REGDEF(V3D_BFC),
53 REGDEF(V3D_RFC),
54 REGDEF(V3D_BPCA),
55 REGDEF(V3D_BPCS),
56 REGDEF(V3D_BPOA),
57 REGDEF(V3D_BPOS),
58 REGDEF(V3D_BXCF),
59 REGDEF(V3D_SQRSV0),
60 REGDEF(V3D_SQRSV1),
61 REGDEF(V3D_SQCNTL),
62 REGDEF(V3D_SRQPC),
63 REGDEF(V3D_SRQUA),
64 REGDEF(V3D_SRQUL),
65 REGDEF(V3D_SRQCS),
66 REGDEF(V3D_VPACNTL),
67 REGDEF(V3D_VPMBASE),
68 REGDEF(V3D_PCTRC),
69 REGDEF(V3D_PCTRE),
70 REGDEF(V3D_PCTR0),
71 REGDEF(V3D_PCTRS0),
72 REGDEF(V3D_PCTR1),
73 REGDEF(V3D_PCTRS1),
74 REGDEF(V3D_PCTR2),
75 REGDEF(V3D_PCTRS2),
76 REGDEF(V3D_PCTR3),
77 REGDEF(V3D_PCTRS3),
78 REGDEF(V3D_PCTR4),
79 REGDEF(V3D_PCTRS4),
80 REGDEF(V3D_PCTR5),
81 REGDEF(V3D_PCTRS5),
82 REGDEF(V3D_PCTR6),
83 REGDEF(V3D_PCTRS6),
84 REGDEF(V3D_PCTR7),
85 REGDEF(V3D_PCTRS7),
86 REGDEF(V3D_PCTR8),
87 REGDEF(V3D_PCTRS8),
88 REGDEF(V3D_PCTR9),
89 REGDEF(V3D_PCTRS9),
90 REGDEF(V3D_PCTR10),
91 REGDEF(V3D_PCTRS10),
92 REGDEF(V3D_PCTR11),
93 REGDEF(V3D_PCTRS11),
94 REGDEF(V3D_PCTR12),
95 REGDEF(V3D_PCTRS12),
96 REGDEF(V3D_PCTR13),
97 REGDEF(V3D_PCTRS13),
98 REGDEF(V3D_PCTR14),
99 REGDEF(V3D_PCTRS14),
100 REGDEF(V3D_PCTR15),
101 REGDEF(V3D_PCTRS15),
102 REGDEF(V3D_DBGE),
103 REGDEF(V3D_FDBGO),
104 REGDEF(V3D_FDBGB),
105 REGDEF(V3D_FDBGR),
106 REGDEF(V3D_FDBGS),
107 REGDEF(V3D_ERRSTAT),
108};
109
110int vc4_v3d_debugfs_regs(struct seq_file *m, void *unused)
111{
112 struct drm_info_node *node = (struct drm_info_node *)m->private;
113 struct drm_device *dev = node->minor->dev;
114 struct vc4_dev *vc4 = to_vc4_dev(dev);
115 int i;
116
117 for (i = 0; i < ARRAY_SIZE(vc4_reg_defs); i++) {
118 seq_printf(m, "%s (0x%04x): 0x%08x\n",
119 vc4_reg_defs[i].name, vc4_reg_defs[i].reg,
120 V3D_READ(vc4_reg_defs[i].reg));
121 }
122
123 return 0;
124}
125
126int vc4_v3d_debugfs_ident(struct seq_file *m, void *unused)
127{
128 struct drm_info_node *node = (struct drm_info_node *)m->private;
129 struct drm_device *dev = node->minor->dev;
130 struct vc4_dev *vc4 = to_vc4_dev(dev);
131 uint32_t ident1 = V3D_READ(V3D_IDENT1);
132 uint32_t nslc = VC4_GET_FIELD(ident1, V3D_IDENT1_NSLC);
133 uint32_t tups = VC4_GET_FIELD(ident1, V3D_IDENT1_TUPS);
134 uint32_t qups = VC4_GET_FIELD(ident1, V3D_IDENT1_QUPS);
135
136 seq_printf(m, "Revision: %d\n",
137 VC4_GET_FIELD(ident1, V3D_IDENT1_REV));
138 seq_printf(m, "Slices: %d\n", nslc);
139 seq_printf(m, "TMUs: %d\n", nslc * tups);
140 seq_printf(m, "QPUs: %d\n", nslc * qups);
141 seq_printf(m, "Semaphores: %d\n",
142 VC4_GET_FIELD(ident1, V3D_IDENT1_NSEM));
143
144 return 0;
145}
146#endif /* CONFIG_DEBUG_FS */
147
148static void vc4_v3d_init_hw(struct drm_device *dev)
149{
150 struct vc4_dev *vc4 = to_vc4_dev(dev);
151
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
Eric Anholt553c9422017-03-27 16:10:25 -0700159int vc4_v3d_get_bin_slot(struct vc4_dev *vc4)
160{
161 struct drm_device *dev = vc4->dev;
162 unsigned long irqflags;
163 int slot;
164 uint64_t seqno = 0;
165 struct vc4_exec_info *exec;
166
167try_again:
168 spin_lock_irqsave(&vc4->job_lock, irqflags);
169 slot = ffs(~vc4->bin_alloc_used);
170 if (slot != 0) {
171 /* Switch from ffs() bit index to a 0-based index. */
172 slot--;
173 vc4->bin_alloc_used |= BIT(slot);
174 spin_unlock_irqrestore(&vc4->job_lock, irqflags);
175 return slot;
176 }
177
178 /* Couldn't find an open slot. Wait for render to complete
179 * and try again.
180 */
181 exec = vc4_last_render_job(vc4);
182 if (exec)
183 seqno = exec->seqno;
184 spin_unlock_irqrestore(&vc4->job_lock, irqflags);
185
186 if (seqno) {
187 int ret = vc4_wait_for_seqno(dev, seqno, ~0ull, true);
188
189 if (ret == 0)
190 goto try_again;
191
192 return ret;
193 }
194
195 return -ENOMEM;
196}
197
198/**
199 * vc4_allocate_bin_bo() - allocates the memory that will be used for
200 * tile binning.
201 *
202 * The binner has a limitation that the addresses in the tile state
203 * buffer that point into the tile alloc buffer or binner overflow
204 * memory only have 28 bits (256MB), and the top 4 on the bus for
205 * tile alloc references end up coming from the tile state buffer's
206 * address.
207 *
208 * To work around this, we allocate a single large buffer while V3D is
209 * in use, make sure that it has the top 4 bits constant across its
210 * entire extent, and then put the tile state, tile alloc, and binner
211 * overflow memory inside that buffer.
212 *
213 * This creates a limitation where we may not be able to execute a job
214 * if it doesn't fit within the buffer that we allocated up front.
215 * However, it turns out that 16MB is "enough for anybody", and
216 * real-world applications run into allocation failures from the
217 * overall CMA pool before they make scenes complicated enough to run
218 * out of bin space.
219 */
220int
221vc4_allocate_bin_bo(struct drm_device *drm)
222{
223 struct vc4_dev *vc4 = to_vc4_dev(drm);
224 struct vc4_v3d *v3d = vc4->v3d;
225 uint32_t size = 16 * 1024 * 1024;
226 int ret = 0;
227 struct list_head list;
228
229 /* We may need to try allocating more than once to get a BO
230 * that doesn't cross 256MB. Track the ones we've allocated
231 * that failed so far, so that we can free them when we've got
232 * one that succeeded (if we freed them right away, our next
233 * allocation would probably be the same chunk of memory).
234 */
235 INIT_LIST_HEAD(&list);
236
237 while (true) {
238 struct vc4_bo *bo = vc4_bo_create(drm, size, true);
239
240 if (IS_ERR(bo)) {
241 ret = PTR_ERR(bo);
242
243 dev_err(&v3d->pdev->dev,
244 "Failed to allocate memory for tile binning: "
245 "%d. You may need to enable CMA or give it "
246 "more memory.",
247 ret);
248 break;
249 }
250
251 /* Check if this BO won't trigger the addressing bug. */
252 if ((bo->base.paddr & 0xf0000000) ==
253 ((bo->base.paddr + bo->base.base.size - 1) & 0xf0000000)) {
254 vc4->bin_bo = bo;
255
256 /* Set up for allocating 512KB chunks of
257 * binner memory. The biggest allocation we
258 * need to do is for the initial tile alloc +
259 * tile state buffer. We can render to a
260 * maximum of ((2048*2048) / (32*32) = 4096
261 * tiles in a frame (until we do floating
262 * point rendering, at which point it would be
263 * 8192). Tile state is 48b/tile (rounded to
264 * a page), and tile alloc is 32b/tile
265 * (rounded to a page), plus a page of extra,
266 * for a total of 320kb for our worst-case.
267 * We choose 512kb so that it divides evenly
268 * into our 16MB, and the rest of the 512kb
269 * will be used as storage for the overflow
270 * from the initial 32b CL per bin.
271 */
272 vc4->bin_alloc_size = 512 * 1024;
273 vc4->bin_alloc_used = 0;
274 vc4->bin_alloc_overflow = 0;
275 WARN_ON_ONCE(sizeof(vc4->bin_alloc_used) * 8 !=
276 bo->base.base.size / vc4->bin_alloc_size);
277
278 break;
279 }
280
281 /* Put it on the list to free later, and try again. */
282 list_add(&bo->unref_head, &list);
283 }
284
285 /* Free all the BOs we allocated but didn't choose. */
286 while (!list_empty(&list)) {
287 struct vc4_bo *bo = list_last_entry(&list,
288 struct vc4_bo, unref_head);
289
290 list_del(&bo->unref_head);
291 drm_gem_object_put_unlocked(&bo->base.base);
292 }
293
294 return ret;
295}
296
Eric Anholt001bdb52016-02-05 17:41:49 -0800297#ifdef CONFIG_PM
298static int vc4_v3d_runtime_suspend(struct device *dev)
299{
300 struct vc4_v3d *v3d = dev_get_drvdata(dev);
301 struct vc4_dev *vc4 = v3d->vc4;
302
303 vc4_irq_uninstall(vc4->dev);
304
Eric Anholt553c9422017-03-27 16:10:25 -0700305 drm_gem_object_put_unlocked(&vc4->bin_bo->base.base);
306 vc4->bin_bo = NULL;
307
Eric Anholt001bdb52016-02-05 17:41:49 -0800308 return 0;
309}
310
311static int vc4_v3d_runtime_resume(struct device *dev)
312{
313 struct vc4_v3d *v3d = dev_get_drvdata(dev);
314 struct vc4_dev *vc4 = v3d->vc4;
Eric Anholt553c9422017-03-27 16:10:25 -0700315 int ret;
316
317 ret = vc4_allocate_bin_bo(vc4->dev);
318 if (ret)
319 return ret;
Eric Anholt001bdb52016-02-05 17:41:49 -0800320
321 vc4_v3d_init_hw(vc4->dev);
322 vc4_irq_postinstall(vc4->dev);
323
324 return 0;
325}
326#endif
327
Eric Anholtd3f51682015-03-02 13:01:12 -0800328static int vc4_v3d_bind(struct device *dev, struct device *master, void *data)
329{
330 struct platform_device *pdev = to_platform_device(dev);
331 struct drm_device *drm = dev_get_drvdata(master);
332 struct vc4_dev *vc4 = to_vc4_dev(drm);
333 struct vc4_v3d *v3d = NULL;
Eric Anholtd5b1a782015-11-30 12:13:37 -0800334 int ret;
Eric Anholtd3f51682015-03-02 13:01:12 -0800335
336 v3d = devm_kzalloc(&pdev->dev, sizeof(*v3d), GFP_KERNEL);
337 if (!v3d)
338 return -ENOMEM;
339
Eric Anholt001bdb52016-02-05 17:41:49 -0800340 dev_set_drvdata(dev, v3d);
341
Eric Anholtd3f51682015-03-02 13:01:12 -0800342 v3d->pdev = pdev;
343
344 v3d->regs = vc4_ioremap_regs(pdev, 0);
345 if (IS_ERR(v3d->regs))
346 return PTR_ERR(v3d->regs);
347
348 vc4->v3d = v3d;
Eric Anholt001bdb52016-02-05 17:41:49 -0800349 v3d->vc4 = vc4;
Eric Anholtd3f51682015-03-02 13:01:12 -0800350
351 if (V3D_READ(V3D_IDENT0) != V3D_EXPECTED_IDENT0) {
352 DRM_ERROR("V3D_IDENT0 read 0x%08x instead of 0x%08x\n",
353 V3D_READ(V3D_IDENT0), V3D_EXPECTED_IDENT0);
354 return -EINVAL;
355 }
356
Eric Anholt553c9422017-03-27 16:10:25 -0700357 ret = vc4_allocate_bin_bo(drm);
358 if (ret)
359 return ret;
360
Eric Anholtd5b1a782015-11-30 12:13:37 -0800361 /* Reset the binner overflow address/size at setup, to be sure
362 * we don't reuse an old one.
363 */
364 V3D_WRITE(V3D_BPOA, 0);
365 V3D_WRITE(V3D_BPOS, 0);
366
Eric Anholtd3f51682015-03-02 13:01:12 -0800367 vc4_v3d_init_hw(drm);
368
Eric Anholtd5b1a782015-11-30 12:13:37 -0800369 ret = drm_irq_install(drm, platform_get_irq(pdev, 0));
370 if (ret) {
371 DRM_ERROR("Failed to install IRQ handler\n");
372 return ret;
373 }
374
Eric Anholt3a622342016-11-04 15:58:38 -0700375 pm_runtime_use_autosuspend(dev);
376 pm_runtime_set_autosuspend_delay(dev, 40); /* a little over 2 frames. */
Eric Anholt001bdb52016-02-05 17:41:49 -0800377 pm_runtime_enable(dev);
378
Eric Anholtd3f51682015-03-02 13:01:12 -0800379 return 0;
380}
381
382static void vc4_v3d_unbind(struct device *dev, struct device *master,
383 void *data)
384{
385 struct drm_device *drm = dev_get_drvdata(master);
386 struct vc4_dev *vc4 = to_vc4_dev(drm);
387
Eric Anholt001bdb52016-02-05 17:41:49 -0800388 pm_runtime_disable(dev);
389
Eric Anholtd5b1a782015-11-30 12:13:37 -0800390 drm_irq_uninstall(drm);
391
392 /* Disable the binner's overflow memory address, so the next
393 * driver probe (if any) doesn't try to reuse our old
394 * allocation.
395 */
396 V3D_WRITE(V3D_BPOA, 0);
397 V3D_WRITE(V3D_BPOS, 0);
398
Eric Anholtd3f51682015-03-02 13:01:12 -0800399 vc4->v3d = NULL;
400}
401
Eric Anholt001bdb52016-02-05 17:41:49 -0800402static const struct dev_pm_ops vc4_v3d_pm_ops = {
403 SET_RUNTIME_PM_OPS(vc4_v3d_runtime_suspend, vc4_v3d_runtime_resume, NULL)
404};
405
Eric Anholtd3f51682015-03-02 13:01:12 -0800406static const struct component_ops vc4_v3d_ops = {
407 .bind = vc4_v3d_bind,
408 .unbind = vc4_v3d_unbind,
409};
410
411static int vc4_v3d_dev_probe(struct platform_device *pdev)
412{
413 return component_add(&pdev->dev, &vc4_v3d_ops);
414}
415
416static int vc4_v3d_dev_remove(struct platform_device *pdev)
417{
418 component_del(&pdev->dev, &vc4_v3d_ops);
419 return 0;
420}
421
422static const struct of_device_id vc4_v3d_dt_match[] = {
Eric Anholt90d71162016-03-04 12:32:07 -0800423 { .compatible = "brcm,bcm2835-v3d" },
Eric Anholtd3f51682015-03-02 13:01:12 -0800424 { .compatible = "brcm,vc4-v3d" },
425 {}
426};
427
428struct platform_driver vc4_v3d_driver = {
429 .probe = vc4_v3d_dev_probe,
430 .remove = vc4_v3d_dev_remove,
431 .driver = {
432 .name = "vc4_v3d",
433 .of_match_table = vc4_v3d_dt_match,
Eric Anholt001bdb52016-02-05 17:41:49 -0800434 .pm = &vc4_v3d_pm_ops,
Eric Anholtd3f51682015-03-02 13:01:12 -0800435 },
436};