1 // SPDX-License-Identifier: GPL-2.0+
2 /* Copyright (C) 2014-2018 Broadcom */
4 #include <linux/circ_buf.h>
5 #include <linux/ctype.h>
6 #include <linux/debugfs.h>
7 #include <linux/seq_file.h>
8 #include <linux/string_helpers.h>
10 #include <drm/drm_debugfs.h>
15 #define REGDEF(min_ver, max_ver, reg) { min_ver, max_ver, reg, #reg }
23 static const struct v3d_reg_def v3d_hub_reg_defs
[] = {
24 REGDEF(33, 42, V3D_HUB_AXICFG
),
25 REGDEF(33, 71, V3D_HUB_UIFCFG
),
26 REGDEF(33, 71, V3D_HUB_IDENT0
),
27 REGDEF(33, 71, V3D_HUB_IDENT1
),
28 REGDEF(33, 71, V3D_HUB_IDENT2
),
29 REGDEF(33, 71, V3D_HUB_IDENT3
),
30 REGDEF(33, 71, V3D_HUB_INT_STS
),
31 REGDEF(33, 71, V3D_HUB_INT_MSK_STS
),
33 REGDEF(33, 71, V3D_MMU_CTL
),
34 REGDEF(33, 71, V3D_MMU_VIO_ADDR
),
35 REGDEF(33, 71, V3D_MMU_VIO_ID
),
36 REGDEF(33, 71, V3D_MMU_DEBUG_INFO
),
38 REGDEF(71, 71, V3D_GMP_STATUS(71)),
39 REGDEF(71, 71, V3D_GMP_CFG(71)),
40 REGDEF(71, 71, V3D_GMP_VIO_ADDR(71)),
43 static const struct v3d_reg_def v3d_gca_reg_defs
[] = {
44 REGDEF(33, 33, V3D_GCA_SAFE_SHUTDOWN
),
45 REGDEF(33, 33, V3D_GCA_SAFE_SHUTDOWN_ACK
),
48 static const struct v3d_reg_def v3d_core_reg_defs
[] = {
49 REGDEF(33, 71, V3D_CTL_IDENT0
),
50 REGDEF(33, 71, V3D_CTL_IDENT1
),
51 REGDEF(33, 71, V3D_CTL_IDENT2
),
52 REGDEF(33, 71, V3D_CTL_MISCCFG
),
53 REGDEF(33, 71, V3D_CTL_INT_STS
),
54 REGDEF(33, 71, V3D_CTL_INT_MSK_STS
),
55 REGDEF(33, 71, V3D_CLE_CT0CS
),
56 REGDEF(33, 71, V3D_CLE_CT0CA
),
57 REGDEF(33, 71, V3D_CLE_CT0EA
),
58 REGDEF(33, 71, V3D_CLE_CT1CS
),
59 REGDEF(33, 71, V3D_CLE_CT1CA
),
60 REGDEF(33, 71, V3D_CLE_CT1EA
),
62 REGDEF(33, 71, V3D_PTB_BPCA
),
63 REGDEF(33, 71, V3D_PTB_BPCS
),
65 REGDEF(33, 42, V3D_GMP_STATUS(33)),
66 REGDEF(33, 42, V3D_GMP_CFG(33)),
67 REGDEF(33, 42, V3D_GMP_VIO_ADDR(33)),
69 REGDEF(33, 71, V3D_ERR_FDBGO
),
70 REGDEF(33, 71, V3D_ERR_FDBGB
),
71 REGDEF(33, 71, V3D_ERR_FDBGS
),
72 REGDEF(33, 71, V3D_ERR_STAT
),
75 static const struct v3d_reg_def v3d_csd_reg_defs
[] = {
76 REGDEF(41, 71, V3D_CSD_STATUS
),
77 REGDEF(41, 42, V3D_CSD_CURRENT_CFG0(41)),
78 REGDEF(41, 42, V3D_CSD_CURRENT_CFG1(41)),
79 REGDEF(41, 42, V3D_CSD_CURRENT_CFG2(41)),
80 REGDEF(41, 42, V3D_CSD_CURRENT_CFG3(41)),
81 REGDEF(41, 42, V3D_CSD_CURRENT_CFG4(41)),
82 REGDEF(41, 42, V3D_CSD_CURRENT_CFG5(41)),
83 REGDEF(41, 42, V3D_CSD_CURRENT_CFG6(41)),
84 REGDEF(71, 71, V3D_CSD_CURRENT_CFG0(71)),
85 REGDEF(71, 71, V3D_CSD_CURRENT_CFG1(71)),
86 REGDEF(71, 71, V3D_CSD_CURRENT_CFG2(71)),
87 REGDEF(71, 71, V3D_CSD_CURRENT_CFG3(71)),
88 REGDEF(71, 71, V3D_CSD_CURRENT_CFG4(71)),
89 REGDEF(71, 71, V3D_CSD_CURRENT_CFG5(71)),
90 REGDEF(71, 71, V3D_CSD_CURRENT_CFG6(71)),
91 REGDEF(71, 71, V3D_V7_CSD_CURRENT_CFG7
),
94 static int v3d_v3d_debugfs_regs(struct seq_file
*m
, void *unused
)
96 struct drm_debugfs_entry
*entry
= m
->private;
97 struct drm_device
*dev
= entry
->dev
;
98 struct v3d_dev
*v3d
= to_v3d_dev(dev
);
101 for (i
= 0; i
< ARRAY_SIZE(v3d_hub_reg_defs
); i
++) {
102 const struct v3d_reg_def
*def
= &v3d_hub_reg_defs
[i
];
104 if (v3d
->ver
>= def
->min_ver
&& v3d
->ver
<= def
->max_ver
) {
105 seq_printf(m
, "%s (0x%04x): 0x%08x\n",
106 def
->name
, def
->reg
, V3D_READ(def
->reg
));
110 for (i
= 0; i
< ARRAY_SIZE(v3d_gca_reg_defs
); i
++) {
111 const struct v3d_reg_def
*def
= &v3d_gca_reg_defs
[i
];
113 if (v3d
->ver
>= def
->min_ver
&& v3d
->ver
<= def
->max_ver
) {
114 seq_printf(m
, "%s (0x%04x): 0x%08x\n",
115 def
->name
, def
->reg
, V3D_GCA_READ(def
->reg
));
119 for (core
= 0; core
< v3d
->cores
; core
++) {
120 for (i
= 0; i
< ARRAY_SIZE(v3d_core_reg_defs
); i
++) {
121 const struct v3d_reg_def
*def
= &v3d_core_reg_defs
[i
];
123 if (v3d
->ver
>= def
->min_ver
&& v3d
->ver
<= def
->max_ver
) {
124 seq_printf(m
, "core %d %s (0x%04x): 0x%08x\n",
125 core
, def
->name
, def
->reg
,
126 V3D_CORE_READ(core
, def
->reg
));
130 for (i
= 0; i
< ARRAY_SIZE(v3d_csd_reg_defs
); i
++) {
131 const struct v3d_reg_def
*def
= &v3d_csd_reg_defs
[i
];
133 if (v3d
->ver
>= def
->min_ver
&& v3d
->ver
<= def
->max_ver
) {
134 seq_printf(m
, "core %d %s (0x%04x): 0x%08x\n",
135 core
, def
->name
, def
->reg
,
136 V3D_CORE_READ(core
, def
->reg
));
144 static int v3d_v3d_debugfs_ident(struct seq_file
*m
, void *unused
)
146 struct drm_debugfs_entry
*entry
= m
->private;
147 struct drm_device
*dev
= entry
->dev
;
148 struct v3d_dev
*v3d
= to_v3d_dev(dev
);
149 u32 ident0
, ident1
, ident2
, ident3
, cores
;
152 ident0
= V3D_READ(V3D_HUB_IDENT0
);
153 ident1
= V3D_READ(V3D_HUB_IDENT1
);
154 ident2
= V3D_READ(V3D_HUB_IDENT2
);
155 ident3
= V3D_READ(V3D_HUB_IDENT3
);
156 cores
= V3D_GET_FIELD(ident1
, V3D_HUB_IDENT1_NCORES
);
158 seq_printf(m
, "Revision: %d.%d.%d.%d\n",
159 V3D_GET_FIELD(ident1
, V3D_HUB_IDENT1_TVER
),
160 V3D_GET_FIELD(ident1
, V3D_HUB_IDENT1_REV
),
161 V3D_GET_FIELD(ident3
, V3D_HUB_IDENT3_IPREV
),
162 V3D_GET_FIELD(ident3
, V3D_HUB_IDENT3_IPIDX
));
163 seq_printf(m
, "MMU: %s\n",
164 str_yes_no(ident2
& V3D_HUB_IDENT2_WITH_MMU
));
165 seq_printf(m
, "TFU: %s\n",
166 str_yes_no(ident1
& V3D_HUB_IDENT1_WITH_TFU
));
167 if (v3d
->ver
<= 42) {
168 seq_printf(m
, "TSY: %s\n",
169 str_yes_no(ident1
& V3D_HUB_IDENT1_WITH_TSY
));
171 seq_printf(m
, "MSO: %s\n",
172 str_yes_no(ident1
& V3D_HUB_IDENT1_WITH_MSO
));
173 seq_printf(m
, "L3C: %s (%dkb)\n",
174 str_yes_no(ident1
& V3D_HUB_IDENT1_WITH_L3C
),
175 V3D_GET_FIELD(ident2
, V3D_HUB_IDENT2_L3C_NKB
));
177 for (core
= 0; core
< cores
; core
++) {
179 u32 nslc
, ntmu
, qups
;
181 ident0
= V3D_CORE_READ(core
, V3D_CTL_IDENT0
);
182 ident1
= V3D_CORE_READ(core
, V3D_CTL_IDENT1
);
183 ident2
= V3D_CORE_READ(core
, V3D_CTL_IDENT2
);
184 misccfg
= V3D_CORE_READ(core
, V3D_CTL_MISCCFG
);
186 nslc
= V3D_GET_FIELD(ident1
, V3D_IDENT1_NSLC
);
187 ntmu
= V3D_GET_FIELD(ident1
, V3D_IDENT1_NTMU
);
188 qups
= V3D_GET_FIELD(ident1
, V3D_IDENT1_QUPS
);
190 seq_printf(m
, "Core %d:\n", core
);
191 seq_printf(m
, " Revision: %d.%d\n",
192 V3D_GET_FIELD(ident0
, V3D_IDENT0_VER
),
193 V3D_GET_FIELD(ident1
, V3D_IDENT1_REV
));
194 seq_printf(m
, " Slices: %d\n", nslc
);
195 seq_printf(m
, " TMUs: %d\n", nslc
* ntmu
);
196 seq_printf(m
, " QPUs: %d\n", nslc
* qups
);
197 seq_printf(m
, " Semaphores: %d\n",
198 V3D_GET_FIELD(ident1
, V3D_IDENT1_NSEM
));
199 if (v3d
->ver
<= 42) {
200 seq_printf(m
, " BCG int: %d\n",
201 (ident2
& V3D_IDENT2_BCG_INT
) != 0);
204 seq_printf(m
, " Override TMU: %d\n",
205 (misccfg
& V3D_MISCCFG_OVRTMUOUT
) != 0);
212 static int v3d_debugfs_bo_stats(struct seq_file
*m
, void *unused
)
214 struct drm_debugfs_entry
*entry
= m
->private;
215 struct drm_device
*dev
= entry
->dev
;
216 struct v3d_dev
*v3d
= to_v3d_dev(dev
);
218 mutex_lock(&v3d
->bo_lock
);
219 seq_printf(m
, "allocated bos: %d\n",
220 v3d
->bo_stats
.num_allocated
);
221 seq_printf(m
, "allocated bo size (kb): %ld\n",
222 (long)v3d
->bo_stats
.pages_allocated
<< (PAGE_SHIFT
- 10));
223 mutex_unlock(&v3d
->bo_lock
);
228 static int v3d_measure_clock(struct seq_file
*m
, void *unused
)
230 struct drm_debugfs_entry
*entry
= m
->private;
231 struct drm_device
*dev
= entry
->dev
;
232 struct v3d_dev
*v3d
= to_v3d_dev(dev
);
235 int measure_ms
= 1000;
237 if (v3d
->ver
>= 40) {
238 int cycle_count_reg
= V3D_PCTR_CYCLE_COUNT(v3d
->ver
);
239 V3D_CORE_WRITE(core
, V3D_V4_PCTR_0_SRC_0_3
,
240 V3D_SET_FIELD(cycle_count_reg
,
242 V3D_CORE_WRITE(core
, V3D_V4_PCTR_0_CLR
, 1);
243 V3D_CORE_WRITE(core
, V3D_V4_PCTR_0_EN
, 1);
245 V3D_CORE_WRITE(core
, V3D_V3_PCTR_0_PCTRS0
,
246 V3D_PCTR_CYCLE_COUNT(v3d
->ver
));
247 V3D_CORE_WRITE(core
, V3D_V3_PCTR_0_CLR
, 1);
248 V3D_CORE_WRITE(core
, V3D_V3_PCTR_0_EN
,
249 V3D_V3_PCTR_0_EN_ENABLE
|
253 cycles
= V3D_CORE_READ(core
, V3D_PCTR_0_PCTR0
);
255 seq_printf(m
, "cycles: %d (%d.%d Mhz)\n",
257 cycles
/ (measure_ms
* 1000),
258 (cycles
/ (measure_ms
* 100)) % 10);
263 static int v3d_debugfs_mm(struct seq_file
*m
, void *unused
)
265 struct drm_printer p
= drm_seq_file_printer(m
);
266 struct drm_debugfs_entry
*entry
= m
->private;
267 struct drm_device
*dev
= entry
->dev
;
268 struct v3d_dev
*v3d
= to_v3d_dev(dev
);
270 spin_lock(&v3d
->mm_lock
);
271 drm_mm_print(&v3d
->mm
, &p
);
272 spin_unlock(&v3d
->mm_lock
);
277 static const struct drm_debugfs_info v3d_debugfs_list
[] = {
278 {"v3d_ident", v3d_v3d_debugfs_ident
, 0},
279 {"v3d_regs", v3d_v3d_debugfs_regs
, 0},
280 {"measure_clock", v3d_measure_clock
, 0},
281 {"bo_stats", v3d_debugfs_bo_stats
, 0},
282 {"v3d_mm", v3d_debugfs_mm
, 0},
286 v3d_debugfs_init(struct drm_minor
*minor
)
288 drm_debugfs_add_files(minor
->dev
, v3d_debugfs_list
, ARRAY_SIZE(v3d_debugfs_list
));