1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2017 Etnaviv Project
4 * Copyright (C) 2017 Zodiac Inflight Innovations
7 #include "common.xml.h"
8 #include "etnaviv_gpu.h"
9 #include "etnaviv_perfmon.h"
10 #include "state_hi.xml.h"
12 struct etnaviv_pm_domain
;
14 struct etnaviv_pm_signal
{
18 u32 (*sample
)(struct etnaviv_gpu
*gpu
,
19 const struct etnaviv_pm_domain
*domain
,
20 const struct etnaviv_pm_signal
*signal
);
23 struct etnaviv_pm_domain
{
26 /* profile register */
31 const struct etnaviv_pm_signal
*signal
;
34 struct etnaviv_pm_domain_meta
{
35 const struct etnaviv_pm_domain
*domains
;
39 static u32
perf_reg_read(struct etnaviv_gpu
*gpu
,
40 const struct etnaviv_pm_domain
*domain
,
41 const struct etnaviv_pm_signal
*signal
)
43 gpu_write(gpu
, domain
->profile_config
, signal
->data
);
45 return gpu_read(gpu
, domain
->profile_read
);
48 static u32
pipe_reg_read(struct etnaviv_gpu
*gpu
,
49 const struct etnaviv_pm_domain
*domain
,
50 const struct etnaviv_pm_signal
*signal
)
52 u32 clock
= gpu_read(gpu
, VIVS_HI_CLOCK_CONTROL
);
56 for (i
= 0; i
< gpu
->identity
.pixel_pipes
; i
++) {
57 clock
&= ~(VIVS_HI_CLOCK_CONTROL_DEBUG_PIXEL_PIPE__MASK
);
58 clock
|= VIVS_HI_CLOCK_CONTROL_DEBUG_PIXEL_PIPE(i
);
59 gpu_write(gpu
, VIVS_HI_CLOCK_CONTROL
, clock
);
60 gpu_write(gpu
, domain
->profile_config
, signal
->data
);
61 value
+= gpu_read(gpu
, domain
->profile_read
);
64 /* switch back to pixel pipe 0 to prevent GPU hang */
65 clock
&= ~(VIVS_HI_CLOCK_CONTROL_DEBUG_PIXEL_PIPE__MASK
);
66 clock
|= VIVS_HI_CLOCK_CONTROL_DEBUG_PIXEL_PIPE(0);
67 gpu_write(gpu
, VIVS_HI_CLOCK_CONTROL
, clock
);
72 static u32
hi_total_cycle_read(struct etnaviv_gpu
*gpu
,
73 const struct etnaviv_pm_domain
*domain
,
74 const struct etnaviv_pm_signal
*signal
)
76 u32 reg
= VIVS_HI_PROFILE_TOTAL_CYCLES
;
78 if (gpu
->identity
.model
== chipModel_GC880
||
79 gpu
->identity
.model
== chipModel_GC2000
||
80 gpu
->identity
.model
== chipModel_GC2100
)
81 reg
= VIVS_MC_PROFILE_CYCLE_COUNTER
;
83 return gpu_read(gpu
, reg
);
86 static u32
hi_total_idle_cycle_read(struct etnaviv_gpu
*gpu
,
87 const struct etnaviv_pm_domain
*domain
,
88 const struct etnaviv_pm_signal
*signal
)
90 u32 reg
= VIVS_HI_PROFILE_IDLE_CYCLES
;
92 if (gpu
->identity
.model
== chipModel_GC880
||
93 gpu
->identity
.model
== chipModel_GC2000
||
94 gpu
->identity
.model
== chipModel_GC2100
)
95 reg
= VIVS_HI_PROFILE_TOTAL_CYCLES
;
97 return gpu_read(gpu
, reg
);
100 static const struct etnaviv_pm_domain doms_3d
[] = {
103 .profile_read
= VIVS_MC_PROFILE_HI_READ
,
104 .profile_config
= VIVS_MC_PROFILE_CONFIG2
,
106 .signal
= (const struct etnaviv_pm_signal
[]) {
115 &hi_total_idle_cycle_read
118 "AXI_CYCLES_READ_REQUEST_STALLED",
119 VIVS_MC_PROFILE_CONFIG2_HI_AXI_CYCLES_READ_REQUEST_STALLED
,
123 "AXI_CYCLES_WRITE_REQUEST_STALLED",
124 VIVS_MC_PROFILE_CONFIG2_HI_AXI_CYCLES_WRITE_REQUEST_STALLED
,
128 "AXI_CYCLES_WRITE_DATA_STALLED",
129 VIVS_MC_PROFILE_CONFIG2_HI_AXI_CYCLES_WRITE_DATA_STALLED
,
136 .profile_read
= VIVS_MC_PROFILE_PE_READ
,
137 .profile_config
= VIVS_MC_PROFILE_CONFIG0
,
139 .signal
= (const struct etnaviv_pm_signal
[]) {
141 "PIXEL_COUNT_KILLED_BY_COLOR_PIPE",
142 VIVS_MC_PROFILE_CONFIG0_PE_PIXEL_COUNT_KILLED_BY_COLOR_PIPE
,
146 "PIXEL_COUNT_KILLED_BY_DEPTH_PIPE",
147 VIVS_MC_PROFILE_CONFIG0_PE_PIXEL_COUNT_KILLED_BY_DEPTH_PIPE
,
151 "PIXEL_COUNT_DRAWN_BY_COLOR_PIPE",
152 VIVS_MC_PROFILE_CONFIG0_PE_PIXEL_COUNT_DRAWN_BY_COLOR_PIPE
,
156 "PIXEL_COUNT_DRAWN_BY_DEPTH_PIPE",
157 VIVS_MC_PROFILE_CONFIG0_PE_PIXEL_COUNT_DRAWN_BY_DEPTH_PIPE
,
164 .profile_read
= VIVS_MC_PROFILE_SH_READ
,
165 .profile_config
= VIVS_MC_PROFILE_CONFIG0
,
167 .signal
= (const struct etnaviv_pm_signal
[]) {
170 VIVS_MC_PROFILE_CONFIG0_SH_SHADER_CYCLES
,
175 VIVS_MC_PROFILE_CONFIG0_SH_PS_INST_COUNTER
,
179 "RENDERED_PIXEL_COUNTER",
180 VIVS_MC_PROFILE_CONFIG0_SH_RENDERED_PIXEL_COUNTER
,
185 VIVS_MC_PROFILE_CONFIG0_SH_VS_INST_COUNTER
,
189 "RENDERED_VERTICE_COUNTER",
190 VIVS_MC_PROFILE_CONFIG0_SH_RENDERED_VERTICE_COUNTER
,
194 "VTX_BRANCH_INST_COUNTER",
195 VIVS_MC_PROFILE_CONFIG0_SH_VTX_BRANCH_INST_COUNTER
,
199 "VTX_TEXLD_INST_COUNTER",
200 VIVS_MC_PROFILE_CONFIG0_SH_VTX_TEXLD_INST_COUNTER
,
204 "PXL_BRANCH_INST_COUNTER",
205 VIVS_MC_PROFILE_CONFIG0_SH_PXL_BRANCH_INST_COUNTER
,
209 "PXL_TEXLD_INST_COUNTER",
210 VIVS_MC_PROFILE_CONFIG0_SH_PXL_TEXLD_INST_COUNTER
,
217 .profile_read
= VIVS_MC_PROFILE_PA_READ
,
218 .profile_config
= VIVS_MC_PROFILE_CONFIG1
,
220 .signal
= (const struct etnaviv_pm_signal
[]) {
223 VIVS_MC_PROFILE_CONFIG1_PA_INPUT_VTX_COUNTER
,
227 "INPUT_PRIM_COUNTER",
228 VIVS_MC_PROFILE_CONFIG1_PA_INPUT_PRIM_COUNTER
,
232 "OUTPUT_PRIM_COUNTER",
233 VIVS_MC_PROFILE_CONFIG1_PA_OUTPUT_PRIM_COUNTER
,
237 "DEPTH_CLIPPED_COUNTER",
238 VIVS_MC_PROFILE_CONFIG1_PA_DEPTH_CLIPPED_COUNTER
,
242 "TRIVIAL_REJECTED_COUNTER",
243 VIVS_MC_PROFILE_CONFIG1_PA_TRIVIAL_REJECTED_COUNTER
,
248 VIVS_MC_PROFILE_CONFIG1_PA_CULLED_COUNTER
,
255 .profile_read
= VIVS_MC_PROFILE_SE_READ
,
256 .profile_config
= VIVS_MC_PROFILE_CONFIG1
,
258 .signal
= (const struct etnaviv_pm_signal
[]) {
260 "CULLED_TRIANGLE_COUNT",
261 VIVS_MC_PROFILE_CONFIG1_SE_CULLED_TRIANGLE_COUNT
,
265 "CULLED_LINES_COUNT",
266 VIVS_MC_PROFILE_CONFIG1_SE_CULLED_LINES_COUNT
,
273 .profile_read
= VIVS_MC_PROFILE_RA_READ
,
274 .profile_config
= VIVS_MC_PROFILE_CONFIG1
,
276 .signal
= (const struct etnaviv_pm_signal
[]) {
279 VIVS_MC_PROFILE_CONFIG1_RA_VALID_PIXEL_COUNT
,
284 VIVS_MC_PROFILE_CONFIG1_RA_TOTAL_QUAD_COUNT
,
288 "VALID_QUAD_COUNT_AFTER_EARLY_Z",
289 VIVS_MC_PROFILE_CONFIG1_RA_VALID_QUAD_COUNT_AFTER_EARLY_Z
,
293 "TOTAL_PRIMITIVE_COUNT",
294 VIVS_MC_PROFILE_CONFIG1_RA_TOTAL_PRIMITIVE_COUNT
,
298 "PIPE_CACHE_MISS_COUNTER",
299 VIVS_MC_PROFILE_CONFIG1_RA_PIPE_CACHE_MISS_COUNTER
,
303 "PREFETCH_CACHE_MISS_COUNTER",
304 VIVS_MC_PROFILE_CONFIG1_RA_PREFETCH_CACHE_MISS_COUNTER
,
309 VIVS_MC_PROFILE_CONFIG1_RA_CULLED_QUAD_COUNT
,
316 .profile_read
= VIVS_MC_PROFILE_TX_READ
,
317 .profile_config
= VIVS_MC_PROFILE_CONFIG1
,
319 .signal
= (const struct etnaviv_pm_signal
[]) {
321 "TOTAL_BILINEAR_REQUESTS",
322 VIVS_MC_PROFILE_CONFIG1_TX_TOTAL_BILINEAR_REQUESTS
,
326 "TOTAL_TRILINEAR_REQUESTS",
327 VIVS_MC_PROFILE_CONFIG1_TX_TOTAL_TRILINEAR_REQUESTS
,
331 "TOTAL_DISCARDED_TEXTURE_REQUESTS",
332 VIVS_MC_PROFILE_CONFIG1_TX_TOTAL_DISCARDED_TEXTURE_REQUESTS
,
336 "TOTAL_TEXTURE_REQUESTS",
337 VIVS_MC_PROFILE_CONFIG1_TX_TOTAL_TEXTURE_REQUESTS
,
342 VIVS_MC_PROFILE_CONFIG1_TX_MEM_READ_COUNT
,
346 "MEM_READ_IN_8B_COUNT",
347 VIVS_MC_PROFILE_CONFIG1_TX_MEM_READ_IN_8B_COUNT
,
352 VIVS_MC_PROFILE_CONFIG1_TX_CACHE_MISS_COUNT
,
356 "CACHE_HIT_TEXEL_COUNT",
357 VIVS_MC_PROFILE_CONFIG1_TX_CACHE_HIT_TEXEL_COUNT
,
361 "CACHE_MISS_TEXEL_COUNT",
362 VIVS_MC_PROFILE_CONFIG1_TX_CACHE_MISS_TEXEL_COUNT
,
369 .profile_read
= VIVS_MC_PROFILE_MC_READ
,
370 .profile_config
= VIVS_MC_PROFILE_CONFIG2
,
372 .signal
= (const struct etnaviv_pm_signal
[]) {
374 "TOTAL_READ_REQ_8B_FROM_PIPELINE",
375 VIVS_MC_PROFILE_CONFIG2_MC_TOTAL_READ_REQ_8B_FROM_PIPELINE
,
379 "TOTAL_READ_REQ_8B_FROM_IP",
380 VIVS_MC_PROFILE_CONFIG2_MC_TOTAL_READ_REQ_8B_FROM_IP
,
384 "TOTAL_WRITE_REQ_8B_FROM_PIPELINE",
385 VIVS_MC_PROFILE_CONFIG2_MC_TOTAL_WRITE_REQ_8B_FROM_PIPELINE
,
392 static const struct etnaviv_pm_domain doms_2d
[] = {
395 .profile_read
= VIVS_MC_PROFILE_PE_READ
,
396 .profile_config
= VIVS_MC_PROFILE_CONFIG0
,
398 .signal
= (const struct etnaviv_pm_signal
[]) {
400 "PIXELS_RENDERED_2D",
401 VIVS_MC_PROFILE_CONFIG0_PE_PIXELS_RENDERED_2D
,
408 static const struct etnaviv_pm_domain doms_vg
[] = {
411 static const struct etnaviv_pm_domain_meta doms_meta
[] = {
413 .nr_domains
= ARRAY_SIZE(doms_3d
),
414 .domains
= &doms_3d
[0]
417 .nr_domains
= ARRAY_SIZE(doms_2d
),
418 .domains
= &doms_2d
[0]
421 .nr_domains
= ARRAY_SIZE(doms_vg
),
422 .domains
= &doms_vg
[0]
426 int etnaviv_pm_query_dom(struct etnaviv_gpu
*gpu
,
427 struct drm_etnaviv_pm_domain
*domain
)
429 const struct etnaviv_pm_domain_meta
*meta
= &doms_meta
[domain
->pipe
];
430 const struct etnaviv_pm_domain
*dom
;
432 if (domain
->iter
>= meta
->nr_domains
)
435 dom
= meta
->domains
+ domain
->iter
;
437 domain
->id
= domain
->iter
;
438 domain
->nr_signals
= dom
->nr_signals
;
439 strncpy(domain
->name
, dom
->name
, sizeof(domain
->name
));
442 if (domain
->iter
== meta
->nr_domains
)
448 int etnaviv_pm_query_sig(struct etnaviv_gpu
*gpu
,
449 struct drm_etnaviv_pm_signal
*signal
)
451 const struct etnaviv_pm_domain_meta
*meta
= &doms_meta
[signal
->pipe
];
452 const struct etnaviv_pm_domain
*dom
;
453 const struct etnaviv_pm_signal
*sig
;
455 if (signal
->domain
>= meta
->nr_domains
)
458 dom
= meta
->domains
+ signal
->domain
;
460 if (signal
->iter
>= dom
->nr_signals
)
463 sig
= &dom
->signal
[signal
->iter
];
465 signal
->id
= signal
->iter
;
466 strncpy(signal
->name
, sig
->name
, sizeof(signal
->name
));
469 if (signal
->iter
== dom
->nr_signals
)
470 signal
->iter
= 0xffff;
475 int etnaviv_pm_req_validate(const struct drm_etnaviv_gem_submit_pmr
*r
,
478 const struct etnaviv_pm_domain_meta
*meta
= &doms_meta
[exec_state
];
479 const struct etnaviv_pm_domain
*dom
;
481 if (r
->domain
>= meta
->nr_domains
)
484 dom
= meta
->domains
+ r
->domain
;
486 if (r
->signal
>= dom
->nr_signals
)
492 void etnaviv_perfmon_process(struct etnaviv_gpu
*gpu
,
493 const struct etnaviv_perfmon_request
*pmr
, u32 exec_state
)
495 const struct etnaviv_pm_domain_meta
*meta
= &doms_meta
[exec_state
];
496 const struct etnaviv_pm_domain
*dom
;
497 const struct etnaviv_pm_signal
*sig
;
498 u32
*bo
= pmr
->bo_vma
;
501 dom
= meta
->domains
+ pmr
->domain
;
502 sig
= &dom
->signal
[pmr
->signal
];
503 val
= sig
->sample(gpu
, dom
, sig
);
505 *(bo
+ pmr
->offset
) = val
;