forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-01-04 1543e317f1da31b75942316931e8f491a8920811
kernel/drivers/gpu/drm/vc4/vc4_v3d.c
....@@ -1,150 +1,159 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Copyright (c) 2014 The Linux Foundation. All rights reserved.
34 * Copyright (C) 2013 Red Hat
45 * 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/>.
176 */
187
198 #include <linux/clk.h>
209 #include <linux/component.h>
10
+#include <linux/platform_device.h>
2111 #include <linux/pm_runtime.h>
12
+
13
+#include <drm/drm_irq.h>
14
+
2215 #include "vc4_drv.h"
2316 #include "vc4_regs.h"
2417
25
-#ifdef CONFIG_DEBUG_FS
26
-#define REGDEF(reg) { reg, #reg }
27
-static const struct {
28
- uint32_t reg;
29
- const char *name;
30
-} vc4_reg_defs[] = {
31
- REGDEF(V3D_IDENT0),
32
- REGDEF(V3D_IDENT1),
33
- REGDEF(V3D_IDENT2),
34
- REGDEF(V3D_SCRATCH),
35
- REGDEF(V3D_L2CACTL),
36
- REGDEF(V3D_SLCACTL),
37
- REGDEF(V3D_INTCTL),
38
- REGDEF(V3D_INTENA),
39
- REGDEF(V3D_INTDIS),
40
- REGDEF(V3D_CT0CS),
41
- REGDEF(V3D_CT1CS),
42
- REGDEF(V3D_CT0EA),
43
- REGDEF(V3D_CT1EA),
44
- REGDEF(V3D_CT0CA),
45
- REGDEF(V3D_CT1CA),
46
- REGDEF(V3D_CT00RA0),
47
- REGDEF(V3D_CT01RA0),
48
- REGDEF(V3D_CT0LC),
49
- REGDEF(V3D_CT1LC),
50
- REGDEF(V3D_CT0PC),
51
- REGDEF(V3D_CT1PC),
52
- REGDEF(V3D_PCS),
53
- REGDEF(V3D_BFC),
54
- REGDEF(V3D_RFC),
55
- REGDEF(V3D_BPCA),
56
- REGDEF(V3D_BPCS),
57
- REGDEF(V3D_BPOA),
58
- REGDEF(V3D_BPOS),
59
- REGDEF(V3D_BXCF),
60
- REGDEF(V3D_SQRSV0),
61
- REGDEF(V3D_SQRSV1),
62
- REGDEF(V3D_SQCNTL),
63
- REGDEF(V3D_SRQPC),
64
- REGDEF(V3D_SRQUA),
65
- REGDEF(V3D_SRQUL),
66
- REGDEF(V3D_SRQCS),
67
- REGDEF(V3D_VPACNTL),
68
- REGDEF(V3D_VPMBASE),
69
- REGDEF(V3D_PCTRC),
70
- REGDEF(V3D_PCTRE),
71
- REGDEF(V3D_PCTR(0)),
72
- REGDEF(V3D_PCTRS(0)),
73
- REGDEF(V3D_PCTR(1)),
74
- REGDEF(V3D_PCTRS(1)),
75
- REGDEF(V3D_PCTR(2)),
76
- REGDEF(V3D_PCTRS(2)),
77
- REGDEF(V3D_PCTR(3)),
78
- REGDEF(V3D_PCTRS(3)),
79
- REGDEF(V3D_PCTR(4)),
80
- REGDEF(V3D_PCTRS(4)),
81
- REGDEF(V3D_PCTR(5)),
82
- REGDEF(V3D_PCTRS(5)),
83
- REGDEF(V3D_PCTR(6)),
84
- REGDEF(V3D_PCTRS(6)),
85
- REGDEF(V3D_PCTR(7)),
86
- REGDEF(V3D_PCTRS(7)),
87
- REGDEF(V3D_PCTR(8)),
88
- REGDEF(V3D_PCTRS(8)),
89
- REGDEF(V3D_PCTR(9)),
90
- REGDEF(V3D_PCTRS(9)),
91
- REGDEF(V3D_PCTR(10)),
92
- REGDEF(V3D_PCTRS(10)),
93
- REGDEF(V3D_PCTR(11)),
94
- REGDEF(V3D_PCTRS(11)),
95
- REGDEF(V3D_PCTR(12)),
96
- REGDEF(V3D_PCTRS(12)),
97
- REGDEF(V3D_PCTR(13)),
98
- REGDEF(V3D_PCTRS(13)),
99
- REGDEF(V3D_PCTR(14)),
100
- REGDEF(V3D_PCTRS(14)),
101
- REGDEF(V3D_PCTR(15)),
102
- REGDEF(V3D_PCTRS(15)),
103
- REGDEF(V3D_DBGE),
104
- REGDEF(V3D_FDBGO),
105
- REGDEF(V3D_FDBGB),
106
- REGDEF(V3D_FDBGR),
107
- REGDEF(V3D_FDBGS),
108
- REGDEF(V3D_ERRSTAT),
18
+static const struct debugfs_reg32 v3d_regs[] = {
19
+ VC4_REG32(V3D_IDENT0),
20
+ VC4_REG32(V3D_IDENT1),
21
+ VC4_REG32(V3D_IDENT2),
22
+ VC4_REG32(V3D_SCRATCH),
23
+ VC4_REG32(V3D_L2CACTL),
24
+ VC4_REG32(V3D_SLCACTL),
25
+ VC4_REG32(V3D_INTCTL),
26
+ VC4_REG32(V3D_INTENA),
27
+ VC4_REG32(V3D_INTDIS),
28
+ VC4_REG32(V3D_CT0CS),
29
+ VC4_REG32(V3D_CT1CS),
30
+ VC4_REG32(V3D_CT0EA),
31
+ VC4_REG32(V3D_CT1EA),
32
+ VC4_REG32(V3D_CT0CA),
33
+ VC4_REG32(V3D_CT1CA),
34
+ VC4_REG32(V3D_CT00RA0),
35
+ VC4_REG32(V3D_CT01RA0),
36
+ VC4_REG32(V3D_CT0LC),
37
+ VC4_REG32(V3D_CT1LC),
38
+ VC4_REG32(V3D_CT0PC),
39
+ VC4_REG32(V3D_CT1PC),
40
+ VC4_REG32(V3D_PCS),
41
+ VC4_REG32(V3D_BFC),
42
+ VC4_REG32(V3D_RFC),
43
+ VC4_REG32(V3D_BPCA),
44
+ VC4_REG32(V3D_BPCS),
45
+ VC4_REG32(V3D_BPOA),
46
+ VC4_REG32(V3D_BPOS),
47
+ VC4_REG32(V3D_BXCF),
48
+ VC4_REG32(V3D_SQRSV0),
49
+ VC4_REG32(V3D_SQRSV1),
50
+ VC4_REG32(V3D_SQCNTL),
51
+ VC4_REG32(V3D_SRQPC),
52
+ VC4_REG32(V3D_SRQUA),
53
+ VC4_REG32(V3D_SRQUL),
54
+ VC4_REG32(V3D_SRQCS),
55
+ VC4_REG32(V3D_VPACNTL),
56
+ VC4_REG32(V3D_VPMBASE),
57
+ VC4_REG32(V3D_PCTRC),
58
+ VC4_REG32(V3D_PCTRE),
59
+ VC4_REG32(V3D_PCTR(0)),
60
+ VC4_REG32(V3D_PCTRS(0)),
61
+ VC4_REG32(V3D_PCTR(1)),
62
+ VC4_REG32(V3D_PCTRS(1)),
63
+ VC4_REG32(V3D_PCTR(2)),
64
+ VC4_REG32(V3D_PCTRS(2)),
65
+ VC4_REG32(V3D_PCTR(3)),
66
+ VC4_REG32(V3D_PCTRS(3)),
67
+ VC4_REG32(V3D_PCTR(4)),
68
+ VC4_REG32(V3D_PCTRS(4)),
69
+ VC4_REG32(V3D_PCTR(5)),
70
+ VC4_REG32(V3D_PCTRS(5)),
71
+ VC4_REG32(V3D_PCTR(6)),
72
+ VC4_REG32(V3D_PCTRS(6)),
73
+ VC4_REG32(V3D_PCTR(7)),
74
+ VC4_REG32(V3D_PCTRS(7)),
75
+ VC4_REG32(V3D_PCTR(8)),
76
+ VC4_REG32(V3D_PCTRS(8)),
77
+ VC4_REG32(V3D_PCTR(9)),
78
+ VC4_REG32(V3D_PCTRS(9)),
79
+ VC4_REG32(V3D_PCTR(10)),
80
+ VC4_REG32(V3D_PCTRS(10)),
81
+ VC4_REG32(V3D_PCTR(11)),
82
+ VC4_REG32(V3D_PCTRS(11)),
83
+ VC4_REG32(V3D_PCTR(12)),
84
+ VC4_REG32(V3D_PCTRS(12)),
85
+ VC4_REG32(V3D_PCTR(13)),
86
+ VC4_REG32(V3D_PCTRS(13)),
87
+ VC4_REG32(V3D_PCTR(14)),
88
+ VC4_REG32(V3D_PCTRS(14)),
89
+ VC4_REG32(V3D_PCTR(15)),
90
+ VC4_REG32(V3D_PCTRS(15)),
91
+ VC4_REG32(V3D_DBGE),
92
+ VC4_REG32(V3D_FDBGO),
93
+ VC4_REG32(V3D_FDBGB),
94
+ VC4_REG32(V3D_FDBGR),
95
+ VC4_REG32(V3D_FDBGS),
96
+ VC4_REG32(V3D_ERRSTAT),
10997 };
11098
111
-int vc4_v3d_debugfs_regs(struct seq_file *m, void *unused)
99
+static int vc4_v3d_debugfs_ident(struct seq_file *m, void *unused)
112100 {
113101 struct drm_info_node *node = (struct drm_info_node *)m->private;
114102 struct drm_device *dev = node->minor->dev;
115103 struct vc4_dev *vc4 = to_vc4_dev(dev);
116
- int i;
104
+ int ret = vc4_v3d_pm_get(vc4);
117105
118
- for (i = 0; i < ARRAY_SIZE(vc4_reg_defs); i++) {
119
- seq_printf(m, "%s (0x%04x): 0x%08x\n",
120
- vc4_reg_defs[i].name, vc4_reg_defs[i].reg,
121
- V3D_READ(vc4_reg_defs[i].reg));
106
+ if (ret == 0) {
107
+ uint32_t ident1 = V3D_READ(V3D_IDENT1);
108
+ uint32_t nslc = VC4_GET_FIELD(ident1, V3D_IDENT1_NSLC);
109
+ uint32_t tups = VC4_GET_FIELD(ident1, V3D_IDENT1_TUPS);
110
+ uint32_t qups = VC4_GET_FIELD(ident1, V3D_IDENT1_QUPS);
111
+
112
+ seq_printf(m, "Revision: %d\n",
113
+ VC4_GET_FIELD(ident1, V3D_IDENT1_REV));
114
+ seq_printf(m, "Slices: %d\n", nslc);
115
+ seq_printf(m, "TMUs: %d\n", nslc * tups);
116
+ seq_printf(m, "QPUs: %d\n", nslc * qups);
117
+ seq_printf(m, "Semaphores: %d\n",
118
+ VC4_GET_FIELD(ident1, V3D_IDENT1_NSEM));
119
+ vc4_v3d_pm_put(vc4);
122120 }
123121
124122 return 0;
125123 }
126124
127
-int vc4_v3d_debugfs_ident(struct seq_file *m, void *unused)
125
+/**
126
+ * Wraps pm_runtime_get_sync() in a refcount, so that we can reliably
127
+ * get the pm_runtime refcount to 0 in vc4_reset().
128
+ */
129
+int
130
+vc4_v3d_pm_get(struct vc4_dev *vc4)
128131 {
129
- struct drm_info_node *node = (struct drm_info_node *)m->private;
130
- struct drm_device *dev = node->minor->dev;
131
- struct vc4_dev *vc4 = to_vc4_dev(dev);
132
- uint32_t ident1 = V3D_READ(V3D_IDENT1);
133
- uint32_t nslc = VC4_GET_FIELD(ident1, V3D_IDENT1_NSLC);
134
- uint32_t tups = VC4_GET_FIELD(ident1, V3D_IDENT1_TUPS);
135
- uint32_t qups = VC4_GET_FIELD(ident1, V3D_IDENT1_QUPS);
132
+ mutex_lock(&vc4->power_lock);
133
+ if (vc4->power_refcount++ == 0) {
134
+ int ret = pm_runtime_get_sync(&vc4->v3d->pdev->dev);
136135
137
- seq_printf(m, "Revision: %d\n",
138
- VC4_GET_FIELD(ident1, V3D_IDENT1_REV));
139
- seq_printf(m, "Slices: %d\n", nslc);
140
- seq_printf(m, "TMUs: %d\n", nslc * tups);
141
- seq_printf(m, "QPUs: %d\n", nslc * qups);
142
- seq_printf(m, "Semaphores: %d\n",
143
- VC4_GET_FIELD(ident1, V3D_IDENT1_NSEM));
136
+ if (ret < 0) {
137
+ vc4->power_refcount--;
138
+ mutex_unlock(&vc4->power_lock);
139
+ return ret;
140
+ }
141
+ }
142
+ mutex_unlock(&vc4->power_lock);
144143
145144 return 0;
146145 }
147
-#endif /* CONFIG_DEBUG_FS */
146
+
147
+void
148
+vc4_v3d_pm_put(struct vc4_dev *vc4)
149
+{
150
+ mutex_lock(&vc4->power_lock);
151
+ if (--vc4->power_refcount == 0) {
152
+ pm_runtime_mark_last_busy(&vc4->v3d->pdev->dev);
153
+ pm_runtime_put_autosuspend(&vc4->v3d->pdev->dev);
154
+ }
155
+ mutex_unlock(&vc4->power_lock);
156
+}
148157
149158 static void vc4_v3d_init_hw(struct drm_device *dev)
150159 {
....@@ -159,7 +168,7 @@
159168
160169 int vc4_v3d_get_bin_slot(struct vc4_dev *vc4)
161170 {
162
- struct drm_device *dev = vc4->dev;
171
+ struct drm_device *dev = &vc4->base;
163172 unsigned long irqflags;
164173 int slot;
165174 uint64_t seqno = 0;
....@@ -197,7 +206,7 @@
197206 }
198207
199208 /**
200
- * vc4_allocate_bin_bo() - allocates the memory that will be used for
209
+ * bin_bo_alloc() - allocates the memory that will be used for
201210 * tile binning.
202211 *
203212 * The binner has a limitation that the addresses in the tile state
....@@ -218,13 +227,15 @@
218227 * overall CMA pool before they make scenes complicated enough to run
219228 * out of bin space.
220229 */
221
-static int vc4_allocate_bin_bo(struct drm_device *drm)
230
+static int bin_bo_alloc(struct vc4_dev *vc4)
222231 {
223
- struct vc4_dev *vc4 = to_vc4_dev(drm);
224232 struct vc4_v3d *v3d = vc4->v3d;
225233 uint32_t size = 16 * 1024 * 1024;
226234 int ret = 0;
227235 struct list_head list;
236
+
237
+ if (!v3d)
238
+ return -ENODEV;
228239
229240 /* We may need to try allocating more than once to get a BO
230241 * that doesn't cross 256MB. Track the ones we've allocated
....@@ -235,7 +246,7 @@
235246 INIT_LIST_HEAD(&list);
236247
237248 while (true) {
238
- struct vc4_bo *bo = vc4_bo_create(drm, size, true,
249
+ struct vc4_bo *bo = vc4_bo_create(&vc4->base, size, true,
239250 VC4_BO_TYPE_BIN);
240251
241252 if (IS_ERR(bo)) {
....@@ -276,6 +287,14 @@
276287 WARN_ON_ONCE(sizeof(vc4->bin_alloc_used) * 8 !=
277288 bo->base.base.size / vc4->bin_alloc_size);
278289
290
+ kref_init(&vc4->bin_bo_kref);
291
+
292
+ /* Enable the out-of-memory interrupt to set our
293
+ * newly-allocated binner BO, potentially from an
294
+ * already-pending-but-masked interrupt.
295
+ */
296
+ V3D_WRITE(V3D_INTENA, V3D_INT_OUTOMEM);
297
+
279298 break;
280299 }
281300
....@@ -289,10 +308,51 @@
289308 struct vc4_bo, unref_head);
290309
291310 list_del(&bo->unref_head);
292
- drm_gem_object_put_unlocked(&bo->base.base);
311
+ drm_gem_object_put(&bo->base.base);
293312 }
294313
295314 return ret;
315
+}
316
+
317
+int vc4_v3d_bin_bo_get(struct vc4_dev *vc4, bool *used)
318
+{
319
+ int ret = 0;
320
+
321
+ mutex_lock(&vc4->bin_bo_lock);
322
+
323
+ if (used && *used)
324
+ goto complete;
325
+
326
+ if (vc4->bin_bo)
327
+ kref_get(&vc4->bin_bo_kref);
328
+ else
329
+ ret = bin_bo_alloc(vc4);
330
+
331
+ if (ret == 0 && used)
332
+ *used = true;
333
+
334
+complete:
335
+ mutex_unlock(&vc4->bin_bo_lock);
336
+
337
+ return ret;
338
+}
339
+
340
+static void bin_bo_release(struct kref *ref)
341
+{
342
+ struct vc4_dev *vc4 = container_of(ref, struct vc4_dev, bin_bo_kref);
343
+
344
+ if (WARN_ON_ONCE(!vc4->bin_bo))
345
+ return;
346
+
347
+ drm_gem_object_put(&vc4->bin_bo->base.base);
348
+ vc4->bin_bo = NULL;
349
+}
350
+
351
+void vc4_v3d_bin_bo_put(struct vc4_dev *vc4)
352
+{
353
+ mutex_lock(&vc4->bin_bo_lock);
354
+ kref_put(&vc4->bin_bo_kref, bin_bo_release);
355
+ mutex_unlock(&vc4->bin_bo_lock);
296356 }
297357
298358 #ifdef CONFIG_PM
....@@ -301,10 +361,7 @@
301361 struct vc4_v3d *v3d = dev_get_drvdata(dev);
302362 struct vc4_dev *vc4 = v3d->vc4;
303363
304
- vc4_irq_uninstall(vc4->dev);
305
-
306
- drm_gem_object_put_unlocked(&vc4->bin_bo->base.base);
307
- vc4->bin_bo = NULL;
364
+ vc4_irq_uninstall(&vc4->base);
308365
309366 clk_disable_unprepare(v3d->clk);
310367
....@@ -317,19 +374,15 @@
317374 struct vc4_dev *vc4 = v3d->vc4;
318375 int ret;
319376
320
- ret = vc4_allocate_bin_bo(vc4->dev);
321
- if (ret)
322
- return ret;
323
-
324377 ret = clk_prepare_enable(v3d->clk);
325378 if (ret != 0)
326379 return ret;
327380
328
- vc4_v3d_init_hw(vc4->dev);
381
+ vc4_v3d_init_hw(&vc4->base);
329382
330383 /* We disabled the IRQ as part of vc4_irq_uninstall in suspend. */
331
- enable_irq(vc4->dev->irq);
332
- vc4_irq_postinstall(vc4->dev);
384
+ enable_irq(vc4->base.irq);
385
+ vc4_irq_postinstall(&vc4->base);
333386
334387 return 0;
335388 }
....@@ -354,6 +407,9 @@
354407 v3d->regs = vc4_ioremap_regs(pdev, 0);
355408 if (IS_ERR(v3d->regs))
356409 return PTR_ERR(v3d->regs);
410
+ v3d->regset.base = v3d->regs;
411
+ v3d->regset.regs = v3d_regs;
412
+ v3d->regset.nregs = ARRAY_SIZE(v3d_regs);
357413
358414 vc4->v3d = v3d;
359415 v3d->vc4 = vc4;
....@@ -384,12 +440,6 @@
384440 if (ret != 0)
385441 return ret;
386442
387
- ret = vc4_allocate_bin_bo(drm);
388
- if (ret) {
389
- clk_disable_unprepare(v3d->clk);
390
- return ret;
391
- }
392
-
393443 /* Reset the binner overflow address/size at setup, to be sure
394444 * we don't reuse an old one.
395445 */
....@@ -408,6 +458,9 @@
408458 pm_runtime_use_autosuspend(dev);
409459 pm_runtime_set_autosuspend_delay(dev, 40); /* a little over 2 frames. */
410460 pm_runtime_enable(dev);
461
+
462
+ vc4_debugfs_add_file(drm, "v3d_ident", vc4_v3d_debugfs_ident, NULL);
463
+ vc4_debugfs_add_regset32(drm, "v3d_regs", &v3d->regset);
411464
412465 return 0;
413466 }
....@@ -452,7 +505,7 @@
452505 return 0;
453506 }
454507
455
-static const struct of_device_id vc4_v3d_dt_match[] = {
508
+const struct of_device_id vc4_v3d_dt_match[] = {
456509 { .compatible = "brcm,bcm2835-v3d" },
457510 { .compatible = "brcm,cygnus-v3d" },
458511 { .compatible = "brcm,vc4-v3d" },